如何编写迁移以在Rails中重命名ActiveRecord模型及其表?


408

我很讨厌命名,并且意识到在Rails应用程序中有更好的模型名称集。
有什么方法可以使用迁移来重命名模型及其对应的表?


11
我建议向此问题添加“ ActiveRecord”以改善搜索引擎的匹配度。我一直在寻找使用“ ActiveRecord重命名表”。
兰登·库恩

6
如果使用迁移,则此问题比看起来要复杂。选定的解决方案说,只需更改表名后,返回并手动重命名模型,控制器等即可。如果执行此操作,则以旧名称引用模型的所有旧迁移将失败。因此,当有人克隆您的仓库并尝试运行时rake db:migrate,它将失败。您可以返回并在迁移中更改这些名称,但这会造成混乱。您最好只创建一个全新的模型而不是重命名它。
安德鲁(Andrew)2012年

4
@andrewhannigan:如果有人克隆您的存储库并开始运行,这不是您要讨论的话题rake db:schema:load吗?
istrasci 2013年

3
@istrasci:绝对。实际上,rake db:migrate正是出于安德鲁(Andrew)指出的担忧,我们不鼓励从头开始建立数据库。
朱塞佩

Answers:


584

这是一个例子:

class RenameOldTableToNewTable < ActiveRecord::Migration
  def self.up
    rename_table :old_table_name, :new_table_name
  end

  def self.down
    rename_table :new_table_name, :old_table_name
  end
end

我不得不手动重新命名模型声明文件。

编辑:

在Rails 3.1和4中,您ActiveRecord::Migration::CommandRecorder知道如何撤消rename_table迁移,因此您可以执行以下操作:

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

(您仍然必须仔细检查并手动重命名文件。)


6
@mathee:是的,您必须手动更改它,或者使用可以进行Ruby重构并将其提交到版本控制系统的IDE进行更改。
pupeno 2010年

13
git grep是你的朋友。我现在正在将“活动”重命名为“习惯”:git grep -i activit这非常具有启发性。
Felix Rabe 2012年

1
您还必须更改控制器的内容,对吗?
alemur '02

5
并且不要忘记您的routes.rb!
丹·赫尔曼

26
同样,要注意,您想在rename_table调用中使用表名的复数形式。

66

在Rails 4中,我要做的就是def更改

def change
  rename_table :old_table_name, :new_table_name
end

我所有的索引都由我负责。我不需要通过删除旧索引并添加新索引来手动更新索引。

它也可以使用更改来提高或降低索引。


47

其他答案和注释包括表重命名,文件重命名和代码遍历。

我想补充一些注意事项:

让我们使用我今天面对的一个现实示例:将模型从“商人”重命名为“业务”。

  • 不要忘记在同一迁移中更改相关表和模型的名称。我同时将我的Merchant和MerchantStat模型更改为Business和BusinessStat。否则在执行搜索和替换时,我不得不做太多的挑选工作。
  • 对于通过外键依赖于您的模型的任何其他模型,其他表的外键列名称将从您的原始模型名称派生。因此,您还需要在这些依赖模型上进行一些rename_column调用。例如,我不得不在各种联接表(对于has_and_belongs_to_many关系)和其他从属表(对于常规has_one和has_many关系)中将“ merchant_id”列重命名为“ business_id”。否则,我将以“ business_stat.merchant_id”之类的列指向“ business.id”。这是进行列重命名的一个好答案。
  • grepping时,请记住搜索字符串的单数,复数,大写,小写,甚至大写(可能出现在注释中)版本。
  • 最好先搜索复数形式,然后再搜索单数形式。这样,如果您有不规则的复数(例如在我的商人::企业示例中),则可以使所有不规则的复数正确。否则,您可能最终会以“业务”(3 s)作为中间状态,从而导致更多的搜索和替换。
  • 不要盲目地替换所有情况。如果您的模型名称与常见的编程术语,其他模型中的值或视图中的文本内容冲突,那么您可能最终会过于渴望。在我的示例中,我想将模型名称更改为“业务”,但在UI内容中仍将其称为“商人”。在CanCan中,我还为我的用户提供了“商户”角色-正是商人角色和商户模型之间的混淆使我首先重命名了该模型。

26

您还需要替换索引:

class RenameOldTableToNewTable< ActiveRecord:Migration
  def self.up
    remove_index :old_table_name, :column_name
    rename_table :old_table_name, :new_table_name
    add_index :new_table_name, :column_name
  end 

  def self.down
    remove_index :new_table_name, :column_name
    rename_table :new_table_name, :old_table_name
    add_index :old_table_name, :column_name
  end
end

并重命名文件等,如此处其他答案所述。

请参阅:http : //api.rubyonrails.org/classes/ActiveRecord/Migration.html

确保编写此迁移后可以回滚和前滚。如果您遇到了一些错误并陷入试图影响不再存在的迁移的过程中,则可能会变得棘手。最好清除整个数据库,如果无法回滚,请重新开始。因此请注意,您可能需要备份某些内容。

另外:在schema_db中检查has_或belongs_to或其他定义的其他表中的任何相关列名。您可能还需要编辑它们。

最后,在没有回归测试套件的情况下执行此操作会很麻烦。


11
对于rails 4.0.0.beta1迁移,不需要手动更新索引。AR会自行更新。
freemanoid

1

您可以执行以下命令:rails g migration redirect_ {old_table_name} to {new_table_name}

编辑文件并将此代码添加到方法更改后

named_table:{old_table_name},:{new_table_name}

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.