2011-12-22 8 views
1

私はitemsテーブルを持っています。私は別のペアでいくつかを作成する必要があります。私のスキーマには、equivalent_idが含まれています。これは、パートナーが存在する場合、パートナーのIDを保管します。同じモデルのレコードペアの関係を設定する

モデルに関係を設定するにはどうすればよいですか? has_oneまたはbelongs_toと言うのは奇妙に思えます。なぜなら、ペア内の項目のどちらも他の概念的な方法で支配的ではないからです。

答えて

1

has_oneを使用すると、has_one :equivalent, :class_name => "Item"と表示され、わかりやすく表示されます。

1

1対1の自己参照および双方向の関連付けは、多対多または多対多の自己参照および双方向の関連付けであっても(驚くほど)複雑です。

ただ明確にする:

  • 自己参照:関連アイテムがその持ち主同じクラスのインスタンスです。
  • 双方向性:アイテムが別のものと同等である場合、後者は最初に述べたアイテムと同等です。意味

:他の点では

revolver = Item.create name: 'revolver' 
pistol = Item.create name: 'pistol' 

revolver.equivalent = pistol 
revolver.equivalent # => pistol 
pistol.equivalent # => revolver 

、あなたが項目にequivalent_id設定した場合は、所有者は」equivalent_idも設定する必要があります。

1対1の関連付けは、insert_sqldelete_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 
+0

あなたは、既存の同等のものを置き換えるために同等=をオーバーライドすることができます。そこにはただ一つしかないと仮定します。 – rkb

+0

@rkbそれがとてもシンプルだったら私はとても幸せだろう。私は私の答えで詳細を飛ばしましたが、試してみてください。私は確かに良い答えに投票します。トランザクションは(特に新しいものを作成する前に既存の関係をクリアすることになる)ときどき気まぐれです。もう一度、それは私の意見でそれを行う**最もクリーンな方法です**。 – Damien

関連する問題