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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/471416/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 20:55:16  来源:igfitidea点击:

How do you write a migration to rename an ActiveRecord model and its table in Rails?

ruby-on-railsmigrationrails-activerecord

提问by Readonly

I'm terrible at naming and realize that there are a better set of names for my models in my Rails app.
Is there any way to use a migration to rename a model and its corresponding table?

我在命名方面很糟糕,并意识到在我的 Rails 应用程序中为我的模型提供了一组更好的名称。
有没有办法使用迁移来重命名模型及其对应的表?

回答by Readonly

Here's an example:

下面是一个例子:

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

I had to go and rename the model declaration file manually.

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

Edit:

编辑:

In Rails 3.1 & 4, ActiveRecord::Migration::CommandRecorderknows how to reverse rename_table migrations, so you can do this:

在 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

(You still have to go through and manually rename your files.)

(您仍然必须通过并手动重命名您的文件。)

回答by bfcoder

In Rails 4 all I had to do was the def change

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

def change
  rename_table :old_table_name, :new_table_name
end

And all of my indexes were taken care of for me. I did not need to manually update the indexes by removing the old ones and adding new ones.

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

And it works using the change for going up or down in regards to the indexes as well.

它也适用于索引上升或下降的变化。

回答by armchairdj

The other answers and comments covered table renaming, file renaming, and grepping through your code.

其他答案和评论涵盖了表重命名、文件重命名和 grepping 代码。

I'd like to add a few more caveats:

我想补充几点:

Let's use a real-world example I faced today: renaming a model from 'Merchant' to 'Business.'

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

  • Don't forget to change the names of dependent tables and models in the same migration. I changed my Merchant and MerchantStat models to Business and BusinessStat at the same time. Otherwise I'd have had to do way too much picking and choosing when performing search-and-replace.
  • For any other models that depend on your model via foreign keys, the other tables' foreign-key column names will be derived from your original model name. So you'll also want to do some rename_column calls on these dependent models. For instance, I had to rename the 'merchant_id' column to 'business_id' in various join tables (for has_and_belongs_to_many relationship) and other dependent tables (for normal has_one and has_many relationships). Otherwise I would have ended up with columns like 'business_stat.merchant_id' pointing to 'business.id'. Here's a good answer about doing column renames.
  • When grepping, remember to search for singular, plural, capitalized, lowercase, and even UPPERCASE (which may occur in comments) versions of your strings.
  • It's best to search for plural versions first, then singular. That way if you have an irregular plural - such as in my merchants :: businesses example - you can get all the irregular plurals correct. Otherwise you may end up with, for example, 'businesss' (3 s's) as an intermediate state, resulting in yet more search-and-replace.
  • Don't blindly replace every occurrence. If your model names collide with common programming terms, with values in other models, or with textual content in your views, you may end up being too over-eager. In my example, I wanted to change my model name to 'Business' but still refer to them as 'merchants' in the content in my UI. I also had a 'merchant' role for my users in CanCan - it was the confusion between the merchant role and the Merchant model that caused me to rename the model in the first place.
  • 不要忘记在同一迁移中更改依赖表和模型的名称。我同时将我的 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 秒)作为中间状态,从而导致更多的搜索和替换。
  • 不要盲目地替换每一次出现。如果您的模型名称与常见的编程术语、其他模型中的值或视图中的文本内容发生冲突,那么您最终可能会过于急切。在我的示例中,我想将我的模型名称更改为“Business”,但仍然在我的 UI 内容中将它们称为“merchants”。我还在 CanCan 中为我的用户设置了一个“商人”角色 - 正是商人角色和商人模型之间的混淆导致我首先重命名模型。

回答by Rimian

You also need to replace your indexes:

您还需要替换索引:

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

And rename your files etc, manually as other answers here describe.

并按照此处的其他答案所述手动重命名您的文件等。

See: http://api.rubyonrails.org/classes/ActiveRecord/Migration.html

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

Make sure you can rollback and roll forward after you write this migration. It can get tricky if you get something wrong and get stuck with a migration that tries to effect something that no longer exists. Best trash the whole database and start again if you can't roll back. So be aware you might need to back something up.

确保在编写此迁移后可以回滚和前滚。如果您出错并陷入试图影响不再存在的东西的迁移,这可能会变得棘手。如果无法回滚,最好将整个数据库丢弃并重新开始。所以请注意,您可能需要备份某些内容。

Also: check schema_db for any relevant column names in other tables defined by a has_ or belongs_to or something. You'll probably need to edit those too.

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

And finally, doing this without a regression test suite would be nuts.

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

回答by Mouhamadou Bamba Mboup

You can do execute this command : rails g migration rename_{old_table_name}to{new_table_name}

你可以执行这个命令: rails g migration rename_{old_table_name} to{new_table_name}

after you edit the file and add this code in the method change

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

rename_table :{old_table_name}, :{new_table_name}

rename_table :{old_table_name}, :{new_table_name}