假设我有一个包含以下型号的现有应用程序:
class User < ActiveRecord::Base
has_many :locations, :through => :location_users
end
class Location < ActiveRecord::Base
has_many :users, :through => :location_users
end
如何将此has_many转换为如下所示的has_one关联,就迁移,修剪多个位置的人的记录以及我错过的任何其他内容而言?有没有可以进行此转换的快捷方式?
class User < ActiveRecord::Base
belongs_to :location
end
class Location < ActiveRecord::Base
has_many :users
end
编辑:用户属于一个且只有一个位置
答案 0 :(得分:1)
没有捷径。
编写迁移以将location_id
添加到users
表
class AddLocationIdToUsers < ActiveRecord::Migration
def change
add_column :users, :location_id, :integer
end
end
您可以编写另一个迁移来填充现有用户的location_id。 例如,如果要在locations_users表中填充用户的第一个location_id
class PopulateLocationIdOnUser < ActiveRecord::Migration
def up
#executing direct query to speed up the operation
execute("update users set location_id = (select location_id from locations_users where locations_users.user_id = users.id limit 1)")
end
def down
execute("update users set location_id = null")
end
end
另一次迁移到drop_users表
class DropLocationsUsersTable < ActiveRecord::Migration
def up
drop_table :locations_users
end
def down
create_table :locations_users do |t|
#columns
end
end
end
您也可以通过一次迁移来完成所有这三个步骤。
答案 1 :(得分:1)
这并不是一个简单的方法。根据我的经验,你将不得不做很多手动工作。这就是我的方式:
编写迁移以将user_id
添加到位置表。
运行迁移
添加has_one关系代码。 (就像你上面一样)
class User < ActiveRecord::Base
has_one :location
end
class Location < ActiveRecord::Base
belongs_to :user
end
编写迁移以转换所有现有数据。 (例如location.user = location.users.first
)。但是在这种情况下写一个rake任务可能会更好,因为这只会发生一次,它需要在你的has_many
关系代码中继存在。因此,删除has_many
代码后,您的迁移将无效。
运行您的佣金任务
删除has_many
代码和连接表。
完成所有这些之后,它应该都能正常工作。其他人可能有更好的方法,但这就是我做的方式。