将Rails表从belongs_to迁移到has_and_belongs_to_many

4

目前,我有一个包含client_id(因此,User belongs_to :client)的users表。

我们需要支持将多个客户关联到一个用户,因此我们实现了一个User has_and_belongs_to_many :clients关联。为此,我们:

  • 创建了一个新的clients_users表,其中包含user_idclient_id列;
  • users中删除了client_id

现在,我们如何自动为最初在users表中拥有的每个client_id创建HABTM记录?我们不想失去数据。

我不确定从哪里开始,因为db:migrate不应涉及模型或它们之间的关联,并且在我的情况下执行原始查询可能会变得复杂。


我不明白你如何实现回滚功能。你进行了更改,然后“用户”有了2个ID为2和4的“客户端”。你打算如何将其回滚到用户的belongs_to关系中? - j-dexx
最初,所有在“client_id”中有内容的用户将只有一个关联的HABTM客户端。他们为什么会有两个客户端? - linkyndy
由于有人使用了系统,并给他们“2”,然后一周后你想回滚。你将丢失数据。 - j-dexx
好的,我明白了。你是对的。我会从我的问题中删除回滚部分。 - linkyndy
1个回答

6

只需将新的has_and_belongs_to_many关联添加到UserClient模型中,并运行以下迁移。

这个解决方案来自于http://manuelvanrijn.nl/blog/2013/03/04/rails-belongs-to-to-has-many/

class MultipleClientsForUser < ActiveRecord::Migration
  def up
    create_table :clients_users, id: false do |t|
      t.references :client, :user
    end

    # define the old belongs_to client associate
    User.class_eval do
      belongs_to :single_client, class_name: "Client", foreign_key: "client_id"
    end

    # add the belongs_to client to the has_and_belongs_to_many client
    User.find_each do |user|
      unless user.single_client.nil?
        user.clients << user.single_client
        user.save
      end
    end

    # remove the old client_id column for the belongs_to associate
    remove_column :users, :client_id
  end

  def down
    add_column :users, :client_id, :integer

    User.class_eval do
      belongs_to :single_client, class_name: "Client", foreign_key: "client_id"
    end

    #Note that only one client may be restored in rollback
    User.find_each do |user|
      user.single_client = user.clients.first unless user.clients.empty?
      user.save
    end

    drop_table :clients_users
  end
end

在迁移中使用模型是否安全?所有内容都应该放在单个迁移中吗?当出现错误时会发生什么?如果失败了,会回滚并再次更改列吗? - linkyndy
1
在迁移中使用模型是否安全?这是一种常见的做法。所有内容都应该放在一个迁移中吗?我认为应该一步完成并一步回滚。如果出现故障会发生什么?迁移被包装在事务中,因此如果出现故障,所有更改都将被回滚。 - y.bregey
1
@AndreiHorak,为了在迁移中安全地使用模型,您可以尝试这种方法http://blog.makandra.com/2010/03/how-to-use-models-in-your-migrations-without-killing-kittens/。 - y.bregey
class_eval 是过度设计了。User.belongs_to ... 就足够了。 - codeholic

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