繁体   English   中英

Rails:将has_many转换为has_one关联

[英]Rails: Convert has_many to has_one association

假设我有一个包含以下型号的现有应用程序:

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

编辑:用户属于一个且只有一个位置

没有捷径。

编写迁移以将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. 编写迁移以将user_id添加到位置表。

  2. 运行迁移

  3. 添加has_one关系代码。 (就像你上面的那样)

     class User < ActiveRecord::Base has_one :location end class Location < ActiveRecord::Base belongs_to :user end 
  4. 编写迁移以转换所有现有数据。 (例如location.user = location.users.first )。 但是在这种情况下写一个rake任务可能会更好,因为这只会发生一次,并且需要在你的has_many关系代码中继存在。 因此,一旦删除has_many代码,您的迁移将无效。

  5. 运行你的rake任务

  6. 删除has_many代码和连接表。

在完成所有这一切后,它应该都可以工作 其他人可能有更好的方法,但这就是我做的方式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM