Rails通过关联进行连接

39

在Ruby on Rails中,我想查找城市中的雇主。 假设模型设置如下:

City
has_many :suburbs
has_many :households, :through => suburbs
has_many :people, :through => suburbs

Suburb
has_many :households
has_many people, :through => households
belongs_to :city


Household
has_many :people
belongs_to :suburb

People
belongs_to :household
belongs_to :employer


Employer
has_many :people

我觉得我想要某种雇主加入some_city.people,但我不知道该怎么做。如果人员直接属于城市,我可以加入Employer到人员中,其中city_id是某个值,但我想找到没有这种直接连接的相同数据,我有点迷失。

谢谢。


你是在尝试使用Rails完成这个吗?为什么不直接使用它们的辅助方法呢? - Steve
对不起,您推荐使用哪个辅助方法来解决这个问题? - spitfire109
为什么你不像从“City”一样从“Employer”通过“has_many:through”遍历关系呢? - Sean Hill
不好意思,我不确定最好的方法是什么。 - Steve
雇主可能跨越多个城市,因此不一定属于某个城市。我可以创建一个连接表,但这似乎对于这个问题来说有点繁琐。我可以给人们一个city_id,但这似乎不是规范化的做法,因为这些信息应该通过当前记录可用。 - spitfire109
2个回答

51

使用嵌套连接

Employer.joins({:people => {:household => {:suburb => :city}}}) 

应该会给你所需要的连接表。如果你要从另一个方向遍历,则需要使用复数名称。

City.joins( :suburbs => {:households => {:people => :employers }})

好的,我想这就是我询问的内容。为了澄清语法,如何进行最终关联来识别特定城市呢?比如说,我想查找所有雇用芝加哥人的雇主,而芝加哥的模型ID为1? - spitfire109
1
在它上面添加一个where子句。.where("employers.city IN ? AND employers.id in ?, city, id) - jvans
1
顺便说一下,我正在重写一个名为searchlogic的gem,以使其与active record 3兼容,并且很快就会完成。它使得在您的应用程序中执行此类搜索非常轻松。https://github.com/binarylogic/searchlogic?source=cr - jvans
感谢您的帮助。我选择了另一个答案,但从所有回复中学到了很多。我会关注Searchlogic的最新动态,非常棒的工作。 - spitfire109
@jvans - 谢谢你 - 如果你想要一个雇主,假设你有一个城市,比如说“休斯顿”? - BenKoshy
1
@BKSpurgeon 添加一个 where 子句。Employer.joins({:people => {:household => {:suburb => :city}}}) .where("cities.name = 'Houston'") - jvans

26

您可以按照 jvans 演示的方式进行联接。或者,您可以设置以下关系:

class Employer < ActiveRecord::Base
  has_many :people
  has_many :households, through: :people
  has_many :suburbs, through: :households
  has_many :cities, through: :suburbs
end

class Person < ActiveRecord::Base
  belongs_to :household
  belongs_to :employer
end


class Household < ActiveRecord::Base
  belongs_to :suburb
  has_many :people
end

class Suburb < ActiveRecord::Base
  belongs_to :city
  has_many :households
  has_many :people, through: :households
end

class City < ActiveRecord::Base
  has_many :suburbs
  has_many :households, through: :suburbs
  has_many :people, through: :households
  has_many :employers, through: :people
end
雇主加入城市,反之亦然,您可以直接这样做。

例如:


Employer.joins(:cities).where("cities.name = ?", "Houston").first

SELECT "employers".* FROM "employers" 
INNER JOIN "people" ON "people"."employer_id" = "employers"."id" 
INNER JOIN "households" ON "households"."id" = "people"."household_id" 
INNER JOIN "suburbs" ON "suburbs"."id" = "households"."suburb_id" 
INNER JOIN "cities" ON "cities"."id" = "suburbs"."city_id" WHERE (cities.name = 'Houston') 
LIMIT 1

哇,我完全不知道我可以做出这种关联。让我去实现它,我猜这正是我寻找未来类似查询和其他事情的答案。 - spitfire109
是的,从Rails 3.1开始,嵌套的has_many :through关系运作得非常好。 - Sean Hill

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接