Rails-通过关联加入 VS 检索

Rails-Joins VS Retrieval via Association

我对 when/how 使用 rails' 加入方法与 rails' 关联感到困惑。

我有一组对象以类似火车的方式相互链接:Class A has_many: bs 和 Class B has_many: cs。我想在链接到链接到 A 的所有 B 的所有 c 上调用一个方法。我尝试用 a.bs.cs.some_method 做到这一点并得到

 undefined method 'some_method' for #<bs::ActiveRecord_Associations_CollectionProxy:…>

四处搜索后,我开始明白这意味着 a.bs returns 一个 CollectionProxy 对象,并且您不能调用方法——即使是 class c 有--在 c 个对象的 CollectionProxy 对象上。

我试图找出它应该如何完成,并遇到了 Joins。现在我想知道是否应该使用嵌套连接来做这种事情?我以为我看到了一长串关联被用来做这件事,但我可能错了。

那么,我的问题是:

1-正确的做法是什么?

2-如果可以用 joins 关联链来完成,什么时候应该使用其中一个?

首先,如果您想获取关联对象或方法输出以进行收集,请使用collectmap。 即

  a.bs.collect{|b| b.cs.collect(&:method_name)}.flatten.compact

现在上面的行将以数组格式为您提供结果,但它非常昂贵。为什么因为它会 运行 这样的查询

1) 获取 a 的第一个查询(很好)

2) 使用 IN 查询获取 a 的所有 bs 的第二个查询(这也很好,因为 IN 查询只是 1 个查询,不会花费那么多时间)

3) 第三:现在对于每个 b 它将尝试获取 cs 并且要获取的查询数量 cs 将取决于 b 的计数.这非常昂贵

我们如何优化它

我们将 eager load cs bs 在获取 bs 之后。这种方式不是每次都明确 运行ning 查询 cs,而是 运行 一个 IN 的查询,这很好

 a.bs.includes(:cs).collect{|b| b.cs.collect(&:method_name)}.flatten.compact

详情:

这将 运行 1 个要获取的查询 a,1 个要获取关联的 bs 的查询 a,然后是一个查询以获取 bs 的关联 cs

您可以从此 link 了解预加载概念,它在获取大规模数据时非常有用。 http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations


要获取详细信息,请尝试此操作

#fetch some object for a like this a = A.first

1) a.bs (this will fetch the bs for a in one query 
2) a.bs.includes(:cs) (this will fetch cs as well as bs in two queries .1 query for bs and 1 query for cs) 
3) a.bs.includes(:cs).collect{|b|} (this will display the bs object) 
4) a.bs.includes(:cs).collect{|b| b.cs } (this will display c objects in an array in each b object i.e 2D array something like this #[[c1,c2], [c3,c4], ...]. where [c1, c2] belongs to b1 
5) a.bs.includes(:cs).collect{|b| b.cs.collect(&:method_name)} (this will put the method names in array. you will see arrays in array because of bs has many cs. each single array inside big array represent one b 
6) a.bs.includes(:cs).collect{|b| b.cs.collect(&:method_name)}.flatten.compact (This will make all 2D arrays in single array. read flatten and compact concept.)