2011-06-23 1 views
0

J'ai un modèle de personne:Sortons personnes ActiveRecord reliant deux personne donnée

has_many :from_relationships, :class_name => "Relationship", :foreign_key => "from_person_id" 
has_many :to_relationships, :class_name => "Relationship", :foreign_key => "to_person_id" 

et un modèle de relation avec:

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

Étant donné une personne p1, je veux mettre en œuvre la méthode d'instance p1.people_connecting_to (p2) qui renvoie toutes les personnes qui lient indirectement p1 à l'autre personne p2. Par exemple, si j'ai les relations suivantes:

  • p1 => p3 => p2
  • p1 => p4 => p2
  • p1 => p5 => p6 => p2

Je veux que p1.people_connecting_to (p2) retourne [p3, p4]. Est-il possible de réaliser en une seule requête SQL via ActiveRecord?

Merci :)

EDIT:

Merci Ed, votre réponse me conduit à la solution suivante. J'ai ajouté:

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

et mis en œuvre people_connecting_to comme ceci:

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

Répondre

0

Vous êtes à la recherche d'un algorithm assez complexe. Effectuez une recherche sur breadth-first et depth-first pour obtenir des idées sur la façon d'implémenter une méthode récursive dans votre modèle Personne pour ce faire.

Une suggestion générale: mettre en place des associations de personne à personne dans votre modèle de personne, comme ceci:

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

Ensuite, vous pouvez obtenir une collection de relations avec @ et @ person.from_relations person.to_relations.

En fonction de vos besoins d'application, vous pourriez être en mesure de simplifier encore les choses en traitant avec la direction dans votre modèle de relation, comme ceci:

modèle Personne:

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

modèle de relation

belongs_to :person 
    belongs_to :relation, :class_name => "Person" 
Avec les assocations plus simples, une méthode d'instance dans votre modèle Person pour trouver si deux personnes sont liées ressemblerait à ceci:
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 

Notez qu'il utilise la récursivité. Aussi, je n'ai pas travaillé à travers l'algorithme pour m'assurer qu'il n'y a pas de potentiel pour des boucles infinies dues à des associations cycliques (Joe -> Bob -> Joe -> Bob).

Questions connexes