我有一個items
表,我需要創建一些不同的對。我的模式包含一個equivalent_id
,它存儲夥伴的ID,如果該夥伴存在。在同一模型中設置一對記錄的關係
在模型中建立關係的最佳方法是什麼?看起來很奇怪的是has_one
或belongs_to
,因爲這兩個對中的任何一個都沒有任何概念上的優勢。
我有一個items
表,我需要創建一些不同的對。我的模式包含一個equivalent_id
,它存儲夥伴的ID,如果該夥伴存在。在同一模型中設置一對記錄的關係
在模型中建立關係的最佳方法是什麼?看起來很奇怪的是has_one
或belongs_to
,因爲這兩個對中的任何一個都沒有任何概念上的優勢。
使用has_one
,你可以說has_one :equivalent, :class_name => "Item"
它看起來對我來說是可讀的。
一對一的自我指涉和雙向關聯(令人驚訝的是)更復雜一對多甚至多對多的自我指涉和雙向關聯。
只是要清楚:
這意味着:
revolver = Item.create name: 'revolver'
pistol = Item.create name: 'pistol'
revolver.equivalent = pistol
revolver.equivalent # => pistol
pistol.equivalent # => revolver
換句話說,當你設置equivalent_id一個項目,業主equivalent_id也必須設置。
One-to-One關聯不接受insert_sql
和delete_sql
選項。所以它不太漂亮。然而,要做到這一點(IMO)最乾淨的方法是:
class Item < ActiveRecord::Base
has_one :equivalent, class_name: 'Item', foreign_key: 'equivalent_id'
def add_equivalent(other)
self.equivalent = other
other.equivalent = self
end
def remove_equivalent
equivalent.equivalent = nil
self.equivalent = nil
end
end
這種方式,你可以這樣做:
revolver = Item.create name: 'revolver'
pistol = Item.create name: 'pistol'
revolver.add_equivalent(pistol)
revolver.equivalent # => pistol
pistol.equivalent # => revolver
pistol.remove_equivalent
pistol.equivalent # => nil
revolver.equivalent # => nil
編輯:
是安全的,應該清理一下每次添加等價物時的關係。這意味着:
revolver.equivalent # => pistol
pistol.equivalent # => revolver
revolver.add_equivalent(gun)
revolver.equivalent # => gun
pistol.equivalent # => nil
你可以做這樣的:
def add_equivalent(other)
remove_equivalent if equivalent
...
end
您可以覆蓋當量=替換任何現有的等價物。假設只能有一個。 – rkb 2011-12-22 19:41:25
@rkb如果那麼簡單,我會很開心。我在答案中跳過了細節,但可以隨意嘗試發佈。我肯定會爲更好的答案投票。事務有時是反覆無常的(特別是在創建新關係之前清除現有關係)。再次,我認爲這是**最乾淨的方式。 – Damien 2011-12-22 20:54:51