在Rails中重命名表

160

我想重命名一个表...(任何表)

我尝试了这行代码:

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

这很奇怪。我知道第一次它是可以工作的,但现在我收到这个错误:undefined method `rename_table' for ActiveRecord::ConnectionAdapters::SchemaStatements:Module

是否有什么我需要设置的东西?

4个回答

303

请记住,在Rails >= 3.1中,您可以使用change方法。

 class RenameOldTableToNewTable < ActiveRecord::Migration
   def change
     rename_table :old_table_name, :new_table_name
   end 
 end

39
这也将把:old_table_name的所有索引迁移到:new_table_name - Gavin Miller
11
仅仅是一个小评论: 或许可以改为: :old_named_things, :new_named_things,提醒人们在ActiveRecord中表名通常是复数形式。 - Carpela

250

通常您会在迁移中完成这种操作:

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

  def self.down
    rename_table :bar, :foo
  end
end

1
谢谢,那个有效!我还是不明白为什么之前的那一行不行。不过没关系。 - Tommy
@Tommy,rename_table 方法定义在 ActiveRecord::ConnectionAdapters::SchemaStatements 中。它旨在混合到其他模块中使用。如果您想直接运行它,我认为您可以这样做:include ActiveRecord::ConnectionAdapters::SchemaStatements; rename_table :foo, :bar - cam
如果你愿意,你也可以使用ActiveRecord::Migration.rename_table(:foo,:bar)。但是迁移工作最好。你是否还想更改模型的名称或者保留旧的模型名称?如果是这样,你可能需要在ActiveRecord模型中指定表名,使用“set_table_name :bar”。 - Aditya Sanghi
1
你也可以使用'migrations'的新表单,而非'up & down',使用'change'方法进行迁移。示例 - MegaTux
在现代的Rails实现中,使用def change而不是def self.up / def.self.down。后者会静默失败。 - huertanix

24

.rename_table是一个实例方法而不是类方法,因此调用Class.method是行不通的。相反,你需要创建一个类的实例,并在实例上调用该方法,像这样:Class.new.method

[编辑] 在这种情况下,ActiveRecord :: ConnectionAdapters :: SchemaStatements甚至不是一个类(正如cam所指出的),这意味着您甚至不能像我上面说的那样创建它的实例。即使您使用cam的示例class Foo; include ActiveRecord :: ConnectionAdapters :: SchemaStatements; def bar; rename_table; end; end;,它仍然无法工作,因为rename_table会引发异常。

另一方面,ActiveRecord :: ConnectionAdapters :: MysqlAdapter是一个类,很可能是您需要用来重命名表格的类(或者根据您使用的数据库是SQLite还是PostgreSQL)。现在,恰好可以通过Model.connection访问ActiveRecord :: ConnectionAdapters :: MysqlAdapter,因此您完全可以使用应用程序中的任何模型来执行Model.connection.rename_table

但是,如果您想永久重命名一个表,我建议使用迁移来完成。这很容易,并且是使用Rails操作数据库结构的首选方式。下面是如何操作:

# 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

接下来,你可以使用 rake db:migrate 命令(它会调用 self.up 方法)来运行迁移,并且使用 rake db:rollback 命令(它会调用 self.down 方法)撤销迁移。


我认为rename_table是一个实例方法,但它并未在类中定义,所以你建议调用Class.new.method的方式行不通(例如:ActiveRecord::ConnectionAdapters::SchemaStatements.new会导致错误oMethodError: undefined method new' for ActiveRecord::ConnectionAdapters::SchemaStatements:Module`)。 - cam
1
值得一提的是,如果您有一个与正在重命名的表相关联的模型,运行rake db:migraterake db:rollback将不会重命名model.rb文件。您需要手动更改model.rb文件。 - 9monkeys
1
在新版本的Rails(例如5.x)中,您可以使用change方法而不是_self.up_和_self.down_,因为Rails也可以通过此方法执行回滚。所以只需这段代码就足够了: def change rename_table :my_table, :my_new_table end . . . . . 顺便说一下:在change内部,您可以使用以下命令:add_columnadd_indexadd_timestampscreate_tableremove_timestampsrename_columnrename_indexrename_table - Beauty

4
ActiveRecord::Migration.rename_table(:old_table_name, :new_table_name)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接