目前,我有包含
users
的 client_id
表(因此,是 User belongs_to :client
)。
我们需要支持与一个用户关联的多个客户端,因此我们实现了一个
User has_and_belongs_to_many :clients
关联。为此,我们:
clients_users
表,其中包含 user_id
和 client_id
列;client_id
中删除了 users
。现在,我们如何为最初在
client_id
表中的每个 users
自动创建 HABTM 记录?我们不想丢失数据。
我不确定从哪里开始,因为
db:migrate
不应该涉及它们之间的模型或关联,并且在我的情况下执行原始查询可能会变得复杂。
只需将新的
has_and_belongs_to_many
关联添加到 User
和 Client
模型并在迁移后运行。
此解决方案来自 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
我更喜欢在迁移中使用完全独立的存根模型,因为模型定义将来可能会发生变化。
# change relation between user and customer from belongs_to to has_and_belongs_to_many
class MultipleCustomersForUser < ActiveRecord::Migration[7.0]
# stub class for conversion of customer to customers
class User < ActiveRecord::Base
belongs_to :customer
has_and_belongs_to_many :customers
end
class Customer < ActiveRecord::Base; end
def up
create_join_table :users, :customers
User.find_each do |user|
user.customers << user.customer if user.customer.present?
user.save
end
remove_reference :users, :customer
end
def down
add_reference :users, :customer
User.find_each do |user|
user.customer = user.customers.first
user.save
end
drop_join_table :users, :customers
end
end