160

I want to rename a table... (any table.)

I tried this line of code:

ActiveRecord::ConnectionAdapters::SchemaStatements.rename_table(old_name, new_name)

Here's the weird thing. I know I got it working the first time, but now I get this error: undefined method `rename_table' for ActiveRecord::ConnectionAdapters::SchemaStatements:Module

Was there something I need to set?

Arslan Ali
  • 17,418
  • 8
  • 58
  • 76
Tommy
  • 1,809
  • 2
  • 13
  • 13

4 Answers4

303

Remember that in Rails >= 3.1 you can use the change method.

 class RenameOldTableToNewTable < ActiveRecord::Migration
   def change
     rename_table :old_table_name, :new_table_name
   end 
 end
Mikhail Grishko
  • 4,258
  • 3
  • 22
  • 21
  • 39
    This will also migrate any indexes from `:old_table_name` to `:new_table_name` – Gavin Miller Sep 18 '13 at 20:45
  • 10
    Just a little comment: Perhaps change to :old_named_things, :new_named_things to remind people that table names in activerecord are generally pluralised. – Carpela Sep 20 '17 at 12:38
250

You would typically do this sort of thing in a migration:

class RenameFoo < ActiveRecord::Migration
  def self.up
    rename_table :foo, :bar
  end

  def self.down
    rename_table :bar, :foo
  end
end
vergenzt
  • 9,669
  • 4
  • 40
  • 47
cam
  • 14,192
  • 1
  • 44
  • 29
  • 1
    Thanks that worked! I'm still puzzled why the previous line didn't though. Oh well.. – Tommy Jan 08 '11 at 00:55
  • @Tommy, the `rename_table` method is defined in the `ActiveRecord::ConnectionAdapters::SchemaStatements`. It is meant to be mixed in to other modules. If you wanted to run it directly, I think you could do `include ActiveRecord::ConnectionAdapters::SchemaStatements; rename_table :foo, :bar` – cam Jan 08 '11 at 01:06
  • or you could use ActiveRecord::Migration.rename_table(:foo,:bar) if you were so inclined. But migration works best. Would you also want to change the name of the model or want to retain the model name as the old one? If so you may want to specify the table name in the ActiveRecord model using "set_table_name :bar". – Aditya Sanghi Jan 08 '11 at 10:27
  • 1
    You can also use the new form for migrations with the 'change' method instead of up & down. [example](http://stackoverflow.com/a/471425/21087) – MegaTux Dec 06 '11 at 15:41
  • def change, not def self.up / def.self.down in modern Rails implementations. Doing the latter will fail silently. – huertanix Jan 25 '17 at 21:26
24

.rename_table is an instance method, not a class method, so calling Class.method isn't going to work. Instead you'll have to create an instance of the class, and call the method on the instance, like this: Class.new.method.

[EDIT] In this instance, ActiveRecord::ConnectionAdapters::SchemaStatements isn't even a class (as pointed out by cam), which means that you can't even create an instance of it as per what I said above. And even if you used cam's example of class Foo; include ActiveRecord::ConnectionAdapters::SchemaStatements; def bar; rename_table; end; end;, it still wouldn't work as rename_table raises an exception.

On the other hand, ActiveRecord::ConnectionAdapters::MysqlAdapter is a class, and it is likely this class you'd have to use to rename your table (or SQLite or PostgreSQL, depending on what database you're using). Now, as it happens, ActiveRecord::ConnectionAdapters::MysqlAdapter is already accessible through Model.connection, so you should be completely able to do Model.connection.rename_table, using any model in your application. [/EDIT]

However, if you wish to permanently rename a table, I would suggest using a migration to do it. It's easy and the preferred way of manipulating your database structure with Rails. Here's how to do it:

# Commandline
rails generate migration rename_my_table

# In db/migrate/[timestamp]_rename_my_table.rb:
class RenameMyTable < ActiveRecord::Migration
  def self.up
    rename_table :my_table, :my_new_table
  end

  def self.down
    rename_table :my_new_table, :my_table
  end
end

Then, you can run your migration with rake db:migrate (which calls the self.up method), and use rake db:rollback (which calls self.down) to undo the migration.

vonconrad
  • 25,227
  • 7
  • 68
  • 69
  • I agree that `rename_table` is an instance method, but it is not defined in a class, so your suggestion to call `Class.new.method` won't work (for example: `ActiveRecord::ConnectionAdapters::SchemaStatements.new` gives the error `oMethodError: undefined method `new' for ActiveRecord::ConnectionAdapters::SchemaStatements:Module` – cam Jan 08 '11 at 01:08
  • 1
    Also worth pointing out, that if you have a model associated with the table you are renaming, running ```rake db:migrate``` or ```rake db:rollback``` will not rename the model.rb file. You will need to manually change the model.rb file. – 9monkeys Jun 08 '12 at 14:00
  • 1
    In newer Rails versions (e.g. 5.x) you can use a **change** method instead of _self.up_ and _self.down_, because Rails can perform a rollback by this, too. So just this code is enough: `def change` `rename_table :my_table, :my_new_table` `end` . . . . . By the way: Inside of `change` you an use these commands: `add_column`, `add_index`, `add_timestamps`, `create_table`, `remove_timestamps`, `rename_column`, `rename_index`, `rename_table` – Beauty Aug 01 '17 at 17:11
4
ActiveRecord::Migration.rename_table(:old_table_name, :new_table_name)
Arslan Ali
  • 17,418
  • 8
  • 58
  • 76
imsinu9
  • 760
  • 7
  • 12