2011-06-23 27 views
0

与えられた2つの連結のActiveRecordの人々を通じて取得は、私は持つ人のモデル持っている人

belongs_to :from_person, :class_name => "Person" 
belongs_to :to_person, :class_name => "Person" 

人P1を考えると、私はインスタンスメソッドを実装したいですp1.pople_connecting_to(p2)p1を他の人に間接的にリンクするすべての人を返します。p2。

  • P1 => P3 => P2
  • P1 => P4 => P2
  • P1 => P5 => P6 => P2
:たとえば私は、次のような関係を持っている場合

p1.people_connecting_to(p2)に[p3、p4]を返すようにします。 ActiveRecordを介して単一のSQLリクエストで達成することは可能ですか?

感謝:)

EDIT

おかげでエドは、あなたの答えは次のソリューションに私をリードしています。私が追加しました:

has_many :to_relations, :source => :to_person, :through => :from_relationships 
has_many :from_relations, :source => :from_person, :through => :to_relationships 

と、このようなpeople_connecting_toを実装:

def people_connecting_to(other_person) 
    to_relations.joins(:from_relationships).where(:"from_relationships_people.to_person_id" => other_person.id) 
end 

答えて

0

あなたはalgorithmかなり複雑で見ています。 breadth-firstdepth-first検索を検索して、これを行うためにPersonモデルで再帰的メソッドを実装する方法を考えてください。

一つの一般的な提案:このように、あなたのPersonモデルで個人対個人の関連付けを設定します

has_many :from_relations, :source => :from_person, :through => :from_relationships 
    has_many :to_relations, :source => :to_person, :through => :to_relationships 

次に、あなたは、@ person.from_relationsとし、person.to_relations @関係のコレクションを取得することができます。

アプリケーションのニーズに応じて、あなたはこのように、あなたの関係のモデルに方向を扱うことによって、さらに物事を単純化することができる場合があります

人モデル:

has_many :relationships 
    has_many :relations, :through => :relationships 

関係モデル

belongs_to :person 
    belongs_to :relation, :class_name => "Person" 

もっと単純な組み合わせでは、2人の人物が関連しているかどうかを調べるPersonモデルのインスタンスメソッドは、次のようになります。

def related_to?(target) 
    if self == target 
    return true 
    elsif self.relations.empty? 
    return false 
    else 
    return self.relations.each {|relation| relation.related_to?(target)} 
    end 
end 

注意してください再帰を使用します。また、循環的な関連性のために無限ループの可能性がないことを確認するためにアルゴリズムを使っていませんでした(Joe - > Bob - > Joe - > Bob)。

関連する問題