有没有人知道确定Rails关联是否已被急切加载的方法?
我的情况:我有一个结果集,有时其中一个关联是急切加载的,有时则不是。如果它没有急切加载,那么我想使用ActiveRecord的查找查找关联。如果它是急切加载,我想使用检测。
例如,假设我的项目模型中有一个shipping_info对象的“has_many”数组。然后:
如果项目是急切加载的,那么最有效的加载是:
item.shipping_infos.detect { |si| si.region == "United States" }
如果项目未加载,则最有效的加载是:
item.shipping_infos.where(region: "United States").first
但除非我知道它是否是急切的加载,否则我不知道要调用哪些代码来有效地获取记录。如果我在第一种方法没有急切加载时使用它,那么我必须查找超过必要的DB记录。如果我在急切加载时使用第二种方法,那么我的急切加载对象将被忽略。
答案 0 :(得分:54)
在记录上使用.association(name).loaded?
。
对于Rails< 3.1使用loaded_foo?
。
(自Rails 3.1以来不推荐使用。请参阅:https://github.com/rails/rails/issues/472。)
答案 1 :(得分:48)
item.shipping_infos.loaded?
会告诉你。
我必须说,但是这条道路会导致疯狂......在编写测试loaded?
的代码以在#detect
和#find
之间做出决定之前,请确保此实例 相对于正在发生的其他事情而言很重要。
如果这不是您的应用程序所做的最慢的事情,添加额外的代码路径会增加不必要的复杂性。仅仅因为你可能浪费了一点点数据库工作并不意味着你需要修复它 - 它可能无论以任何可衡量的方式都无关紧要。
答案 2 :(得分:21)
我建议使用item.association_cache.keys,它将提供预先加载的关联列表。你是item.association_cache.keys.include吗? :name_of_association
答案 3 :(得分:3)
您可以检测是否已使用loaded_ foo ?加载了单个关联。例如,如果shipping_info是belongs_to关联,那么item.loaded_shipping_info?当它被急切加载时将返回true。奇怪的是,它似乎在没有加载时返回nil(而不是false)(无论如何在Rails 2.3.10中)。
答案 4 :(得分:3)
此问题的解决方案应该是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
答案 5 :(得分:2)
查看Bullet gem.。这将告诉您何时应该而且不应该使用预先加载。
答案 6 :(得分:1)
association_cached?
可能很合适:
item.association_cached?(:shipping_infos)