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

Posted

技术标签:

【中文标题】如何编写迁移以重命名 Rails 中的 ActiveRecord 模型及其表?【英文标题】:How do you write a migration to rename an ActiveRecord model and its table in Rails? 【发布时间】:2010-10-03 01:17:09 【问题描述】:

我不擅长命名,并意识到我的 Rails 应用程序中有一组更好的模型名称。 有没有办法使用迁移来重命名模型及其对应的表?

【问题讨论】:

我建议在这个问题中添加“ActiveRecord”以改进搜索引擎匹配。我一直在寻找这个使用“ActiveRecord 重命名表”。 如果你使用迁移,这个问题比看起来要复杂。选定的解决方案说在您更改表名后返回并手动重命名模型、控制器等。如果您这样做,所有以旧名称引用您的模型的旧迁移都将失败。因此,当有人克隆您的 repo 并尝试运行 rake db:migrate 时,它将失败。您可以返回并在迁移中更改这些名称,但这会变得一团糟。您最好创建一个全新的模型而不是重命名它。 @andrewhannigan:如果有人克隆你的 repo 并运行 rake db:schema:load,你的观点不是没有意义吗? @istrasci:绝对。事实上,我们不鼓励使用rake db:migrate 从头开始​​建立数据库,这正是由于 andrew 指出的担忧。 【参考方案1】:

这是一个例子:

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

(您仍然需要手动重命名文件。)

【讨论】:

@mathee:是的,您必须手动更改它,或者使用可以进行 Ruby 重构并将其提交到您的版本控制系统的 IDE。 git grep 是你的朋友。我现在正在将活动重命名为习惯:git grep -i activit 非常具有启发性。 您还必须更改控制器的内容,对吧? 别忘了你的 routes.rb! 另外,提醒一下,您想在 rename_table 调用中使用表名的复数形式。【参考方案2】:

在 Rails 4 中,我所要做的就是更改定义

def change
  rename_table :old_table_name, :new_table_name
end

我所有的索引都为我处理好了。我不需要通过删除旧索引并添加新索引来手动更新索引。

它也可以使用索引的上升或下降变化来工作。

【讨论】:

【参考方案3】:

其他答案和 cmets 涵盖了表重命名、文件重命名和通过代码查找。

我想补充一些注意事项:

让我们使用我今天遇到的一个真实示例:将模型从“Merchant”重命名为“Business”。

不要忘记更改依赖表和模型的名称 同样的迁移。我同时将 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”的列。 Here's a good answer about doing column renames. grepping 时,记得搜索单数、复数、大写、 小写,甚至大写(可能出现在 cmets 中)版本 你的字符串。 最好先搜索复数版本,然后再搜索单数。那 如果你有不规则的复数形式——比如在我的商人中:: 商业示例 - 您可以正确地获取所有不规则复数。 否则,您最终可能会得到例如“businesss”(3 s)作为 中间状态,导致更多的搜索和替换。 不要盲目替换每一个匹配项。如果您的型号名称发生冲突 使用通用编程术语,使用其他模型中的值,或使用 在你的观点中,你可能会过于渴望。 在我的示例中,我想将模型名称更改为“业务”,但是 在我的 UI 的内容中仍然将它们称为“商家”。我还在 CanCan 中为我的用户设置了一个“商家”角色 - 商家角色和商家模型之间的混淆导致我首先重命名了该模型。

【讨论】:

【参考方案4】:

您还需要替换索引:

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 或其他东西定义的其他表中的任何相关列名。您可能还需要编辑这些内容。

最后,在没有回归测试套件的情况下这样做会很疯狂。

【讨论】:

对于 rails 4.0.0.beta1 迁移,不需要手动更新索引。 AR 会自行更新。【参考方案5】:

你可以 执行此命令:rails g 迁移 重命名_old_table_namenew_table_name

编辑文件并在方法更改中添加此代码后

重命名表:old_table_name,:new_table_name

【讨论】:

以上是关于如何编写迁移以重命名 Rails 中的 ActiveRecord 模型及其表?的主要内容,如果未能解决你的问题,请参考以下文章

如何将现有的一对多关系迁移到 Rails 和 ActiveRecord 中的多对多

如何创建批处理文件以重命名文件夹中的大量文件?

您如何编写 Rails 迁移以删除 schema.rb 中的 :id => false 选项?

如何在Rails中的迁移中编写SQL

命名空间模型中的 Rails 关联

如何通过 Rails 迁移克隆数据库表?