簡體   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