Rails 迁移:使用不同的列作为 id

发布于 2024-11-19 20:38:28 字数 185 浏览 1 评论 0原文

我刚刚开始学习 Rails 迁移。我有一个名为 tags 的表,其中包含 name [string] 列(以及自动生成的 id 列)。我想迁移它,以便表使用 name 列作为 id 和主键。如何确保所有现有记录都适用于新架构?

I'm just starting to learn Rails migrations. I have a table called tags with a column name [string] (and with the auto-generated id column). I want to migrate it so that the table uses the name column as the id and primary key. How do I do this making sure all existing records work with the new schema?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

天暗了我发光 2024-11-26 20:38:28

方法很简单,但执行起来似乎有风险。让迁移工作起来相当简单,但是向下迁移呢?没有把握。

  1. 确保您的名称列在所有记录中都是唯一的
  2. 查找存储对您的对象的引用的所有其他对象并将其从 id 更改为名称。

如果您发现该列不是唯一的,您将必须想出某种计划来更改它...例如名称字段中的名称+ID 以获得重复项或类似的内容。当然,所有这些都可以通过迁移来完成。

我建议将 id 列保留在那里,但仅使用它来解决您在此过程中发现的问题

举例来说,假设这是标签表周围的模型:

class Tag < ActiveRecord::Base
end

假设您至少有另一个模型 Thing,它具有简单的关联使用标签模型:

class Thing < ActiveRecord::Base
   has_one :tag
end

things 表上有一个 tag_id 列。我将添加一个名为 tag_name 的列,更改关联以使外键指向这个新列...

class Thing < ActiveRecord::Base
  has_one :tag, :foreign_key => "tag_name"
end

这告诉 Rails 这些事物之间的关联是通过新列进行的。按照惯例,它将查找“tag_id”。

鉴于此更改,您可以进行迁移并且:

add_column :things, :tag_name, :string

Thing.all.each do |thing| 
  if thing.tag
    thing.tag_name = thing.tag.name
  end
end

remove_column :things, :tag_id

这是一个快速而肮脏的示例,我可能错过了一些东西。关键是添加新列、移动关联、删除旧列。

还有其他场景,例如模型涉及多对多关联或多态关联的情况,但在这些情况下,一般方法是类似的。

The approach is straightforward, but the execution seems risky. getting the migration up working is fairly straight forward, but the down? not sure.

  1. Make sure that your name column is unique across all records
  2. Find all other objects that store a reference to your object and change those from id to name.

If you find that the column is not unique you'll have to come up with some kind of plan to change that...like name+id in the name field for duplicates or something similar. All of this can be done from a migration, of course.

I suggest leaving the id column there but only use it to resolve issues you find along the way

By way of example, assume this is your model around the tags table:

class Tag < ActiveRecord::Base
end

Assume you have at least this other model, Thing, that has a simple association with the Tag model:

class Thing < ActiveRecord::Base
   has_one :tag
end

There is a tag_id column on the things table. I'd add a column called tag_name, change the association to have a foreign key pointing to this new column...

class Thing < ActiveRecord::Base
  has_one :tag, :foreign_key => "tag_name"
end

This tells Rails that the association between these things is through the new column. By convention it would look for "tag_id".

Given this change you can go into the migration and:

add_column :things, :tag_name, :string

Thing.all.each do |thing| 
  if thing.tag
    thing.tag_name = thing.tag.name
  end
end

remove_column :things, :tag_id

This is a quick and dirty example and I might have missed something. the key thing is to add the new column, move the association, remove the old column.

There are other scenarios like the case where the model is involved in a many to many association or some polymorphic association, but the general approach would be similar in those cases.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文