Rails包含并渴望加载

时间:2018-09-04 17:21:59

标签: ruby-on-rails ruby

我有一个Rails命令:

Product.includes(:sale, :product_description).select('distinct on (size) *')

据我了解,当我运行此命令时,Rails会急切地将结果加载到内存中,并且由于只有4种大小,因此结果应仅包含4条记录。但是,如果我做类似的事情:

result = Product.includes(:sale, :product_description).select('distinct on (size) *')

,然后执行:result.size。结果将是所有产品记录的计数,即435。但是,如果我这样做:result.length,我将得到预期的响应,即4。

为什么lengthsize的结果不同?我以为通过使用includes会热切加载所有内容,因此lengthsize应该返回相同的计数?

还请注意,如果我先运行length,然后再运行size,两者都返回正确的结果4。但是,如果我先运行size,则得到的错误响应为435。

1 个答案:

答案 0 :(得分:2)

count上的sizelengthActiveRecord::Relations之间存在细微差别(有关详细信息,请参见this answer

在您的示例中,length将始终执行与ActiveRecord::Relation相同的确切查询,然后在返回的数组上调用length

result.size将在之前未加载count时执行ActiveRecord::Relation查询。由于count返回数字(而不是实际记录),因此查询得到了优化,并且includeselect部分被忽略。从性能的角度来看,这是有道理的。

但是如果Relation已经被加载(例如,当您在length之前调用size),那么size只会返回已经加载的数组的大小。 / p>