通过ActiveRecord人员连接两个给定的人

时间:2011-06-23 23:55:51

标签: ruby-on-rails activerecord

我有一个Person模型:

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

和关系模型:

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

给定一个人p1,我想实现实例方法p1.people_connecting_to(p2),它返回所有将p1间接链接到另一个人p2的人。例如,如果我有以下关系:

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

我希望p1.people_connecting_to(p2)返回[p3,p4]。是否可以通过ActiveRecord在单个SQL请求中实现?

谢谢:)

修改

感谢Ed,您的回答引导我找到以下解决方案。我添加了:

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

1 个答案:

答案 0 :(得分:0)

你正在寻找一个相当复杂的algorithm。搜索breadth-firstdepth-first搜索以获取有关如何在Person模型中实现递归方法的建议。

一个一般性建议:在Person模型中设置Person-to-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"

使用更简单的关联,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)。