如何确定 Rails 协会是否渴望加载?

是否有人知道一种方法来确定 Rails 关联是否已经被迫加载?

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

例如,假设在我的条目模型中有一个 Shipping _ info 对象的“ has _ many”数组,然后:

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

item.shipping_infos.detect { |si| si.region == "United States" }

如果项目没有立即加载,最有效的加载方式是:

item.shipping_infos.where(region: "United States").first

但是,除非我知道它是否渴望加载,否则我不知道调用哪些代码来高效地获取记录。如果我在第一个方法没有立即加载时使用它,那么我必须查找比必要的更多的 DB 记录。如果我使用第二个方法时,它是渴望加载的,那么我的渴望加载的对象将被忽略。

26719 次浏览

item.shipping_infos.loaded?会告诉你。

我必须说,虽然: 这条路径导致疯狂... 之前编写代码测试 loaded?决定之间的 #detect#find,确保这个实例 真的的问题,相对于其他一切正在发生的事情。

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

看一下 子弹宝石。。它会告诉你什么时候应该和不应该使用急加载。

你可以检测一个单独的关联是否已经装载了 _ ?.例如,如果 Shipping _ info 是一个 properties _ to 关联,那么 item.load _ Shipping _ info?将返回真,当它被迫加载。奇怪的是,当它没有被加载时,它似乎返回了 nil (而不是 false)(至少在 Rails 2.3.10中是这样)。

在唱片上使用 .association(name).loaded?


对于 Rails < 3.1,使用 loaded_foo?

(从 Rails 3.1开始就不再使用它了。参见: https://github.com/rails/rails/issues/472。)

这个问题的解决方案应该是 foo.association(:bla).loaded?,但它工作不正确-它检查并标记为脏的关联:

class Foo; has_one :bla, :autosave => true end
foo.association(:bla).loaded? #=> false
foo.save # saves foo and fires select * from bla

因此,我在 ActiveRecord 中添加了以下扩展:

module ActiveRecord
class Base
def association_loaded?(name)
association_instance_get(name).present?
end
end
end

现在:

class Foo; has_one :bla, :autosave => true end
foo.association_loaded?(:bla) #=> false
foo.save # saves foo

我建议使用 item.association _ cache. key,它将提供一个渴望加载的关联列表

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

item.association_cached?(:shipping_infos)