如何确定是否已加载Rails关联?

wbh*_*ing 54 activerecord ruby-on-rails eager-loading

有没有人知道确定Rails关联是否已被急切加载的方法?

我的情况:我有一个结果集,有时其中一个关联是急切加载的,有时它不是.如果它没有急切加载,那么我想使用ActiveRecord的查找查找关联.如果它是急切加载,我想使用检测.

例如,假设我的项目模型中有一个shipping_info对象的"has_many"数组.然后:

如果项目是急切加载的,最有效的负载是:

item.shipping_infos.detect { |si| si.region == "United States" }
Run Code Online (Sandbox Code Playgroud)

如果项目未加载,则最有效的加载是:

item.shipping_infos.where(region: "United States").first
Run Code Online (Sandbox Code Playgroud)

但除非我知道它是否是急切加载,否则我不知道要调用哪些代码来有效地获取记录.如果我在第一种方法没有急切加载时使用它,那么我必须查找超过必要的DB记录.如果我在急切加载时使用第二种方法,那么我的急切加载对象将被忽略.

gam*_*mov 60

使用.association(name).loaded?上的记录.


对于Rails <3.1使用loaded_foo?.

(自Rails 3.1以来不推荐使用.请参阅:https://github.com/rails/rails/issues/472.)


Bry*_*rns 51

item.shipping_infos.loaded? 会告诉你的.

我得说,虽然:这条路通向疯狂...编写测试代码之前loaded?之间做出选择#detect#find,确保这种情况下真正重要的,相对于其他一切事情.

如果这不是您的应用程序所做的最慢的事情,添加额外的代码路径会增加不必要的复杂性.仅仅因为你可能浪费一点点数据库工作并不意味着你需要修复它 - 它可能无论以任何可衡量的方式都无关紧要.

  • 这只适用于has_many协会!在belongs_to的情况下,此调用实际上将加载另一个对象(因此它将始终为true) (11认同)
  • @reto 要在 `has_one`/`belongs_to` 关联中检查这一点,您可以执行 `item.association(:shipping_info).loaded?` ,其工作原理类似。在我的答案中添加了示例和更多详细信息:/sf/answers/4854490441/ (4认同)

dab*_*ert 24

我建议使用item.association_cache.keys,它将提供预先加载的关联列表.你是item.association_cache.keys.include吗?:name_of_association

  • 此语法在 Rails 5 中不再有效(不确定何时更改)。现在是“item.association_cached”?:协会名称`。 (6认同)

phi*_*kov 14

association_cached?可能是一个不错的选择:

item.association_cached?(:shipping_infos)
Run Code Online (Sandbox Code Playgroud)