Rails-通过关联加入VS检索

时间:2015-08-02 16:34:02

标签: ruby-on-rails ruby join associations

我很困惑何时/如何使用rails'Joint方法与rails'Associations。

我有一组对象以类似火车的方式相互链接:类A has_many: bs和类B has_many: cs。我想在与c链接的所有B链接的所有A上调用方法。我尝试使用a.bs.cs.some_method执行此操作并获得

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

在搜索之后,我逐渐明白这意味着a.bs返回一个CollectionProxy对象,你无法调用方法 - 即使是类c具有的方法 - on c个对象的CollectionProxy对象。

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

所以,我的问题是:

1 - 这样做的正确方法是什么?

2 - 如果可以使用joins 关联链接完成,何时应该使用另一个?

1 个答案:

答案 0 :(得分:1)

首先,如果您想获取被收集的被告对象或方法输出,请使用fatal error: unexpectedly found nil while unwrapping an Optional value (lldb)collect。 即

map

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

1)第一次查询以获取 a.bs.collect{|b| b.cs.collect(&:method_name)}.flatten.compact (此罚款)

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

3)第3名:现在,对于每个a,它会尝试获取b,而获取cs的查询数量将取决于cs的数量。这非常昂贵

我们如何优化它

我们将在获取bs后急切加载 b cs。这种方式而不是明确地每次运行bs的查询,它将使用cs运行一个查询,这很好

IN

详情:

这将运行1个查询以获取 a.bs.includes(:cs).collect{|b| b.cs.collect(&:method_name)}.flatten.compact ,1个查询以获取关联的a bs然后使用一个查询来获取a的相关cs

您可以从此链接中了解热切加载概念,并且在获取大规模数据时这是非常有用的概念。 http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations

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

#fetch some this for this bs

a = A.first