Ruby-on-rails 如何确定 Rails Association 是否已加载?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1376212/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to Determine if Rails Association is Eager Loaded?
提问by wbharding
Does anyone know a way to determine if a Rails association has been eager loaded?
有谁知道一种确定 Rails 关联是否已被预先加载的方法?
My situation: I have a result set where sometimes one of the associations is eager loaded, and sometimes it isn't. If it isn't eager-loaded, then I want to look up associations using ActiveRecord's find. If it is eager loaded, I want to use detect.
我的情况:我有一个结果集,有时其中一个关联是急切加载的,有时则不是。如果它不是预先加载的,那么我想使用 ActiveRecord 的 find 查找关联。如果它是预先加载的,我想使用检测。
For example, say that I have a "has_many" array of shipping_info objects in my item model. Then:
例如,假设我的项目模型中有一个“has_many”数组 shipping_info 对象。然后:
If item is eager loaded, most efficient load is:
如果项目是预先加载的,最有效的加载是:
item.shipping_infos.detect { |si| si.region == "United States" }
If item isn't eager loaded, most efficient load is:
如果项目不是预先加载,最有效的加载是:
item.shipping_infos.where(region: "United States").first
But unless I know whether it is eager loaded, I don't know which code to call to get the record efficiently. If I use the first method when it wasn't eager loaded, then I have to look up more DB records than necessary. And if I use the second method when it was eager loaded, then my eager loaded objects are ignored.
但是除非我知道它是否是预先加载的,否则我不知道要调用哪个代码才能有效地获取记录。如果我在没有急切加载时使用第一种方法,那么我必须查找比必要更多的数据库记录。如果我在急切加载时使用第二种方法,那么我急切加载的对象将被忽略。
采纳答案by Bryan Stearns
item.shipping_infos.loaded?will tell you.
item.shipping_infos.loaded?会告诉你。
I gotta say, though: this path leads to madness... before writing code that tests loaded?to decide between #detectand #find, make sure this instance reallymatters, relative to everything else that's going on.
不过,我得说:这条路会导致疯狂……在编写测试loaded?以在#detect和之间#find做出决定的代码之前,确保这个实例真的很重要,相对于正在发生的所有其他事情。
If this isn't the slowest thing your app does, adding extra code paths adds unnecessary complexity. Just because you might waste a little database effort doesn't mean you need to fix it - it probably doesn't matter in any measurable way.
如果这不是您的应用程序所做的最慢的事情,添加额外的代码路径会增加不必要的复杂性。仅仅因为您可能会浪费一点数据库工作并不意味着您需要修复它 - 它可能以任何可衡量的方式无关紧要。
回答by gamov
Use .association(name).loaded?on a record.
使用.association(name).loaded?上的记录。
For Rails < 3.1 use loaded_foo?.
对于 Rails < 3.1 使用loaded_foo?.
(It is deprecated since Rails 3.1. See: https://github.com/rails/rails/issues/472.)
(自 Rails 3.1 起已弃用。请参阅:https: //github.com/rails/rails/issues/472。)
回答by dabobert
I'd suggest using item.association_cache.keys that will provide a list of the eager loaded associations. So you item.association_cache.keys.include?(:name_of_association)
我建议使用 item.association_cache.keys 来提供急切加载关联的列表。那么你item.association_cache.keys.include?(:name_of_association)
回答by phil pirozhkov
association_cached?might be a good fit:
association_cached?可能很合适:
item.association_cached?(:shipping_infos)
回答by Jim Stewart
You can detect whether or not a single association has been loaded with loaded_foo?. For example, if shipping_info was a belongs_to association, then item.loaded_shipping_info? will return true when it's been eager-loaded. Oddly, it appears to return nil (rather than false) when it hasn't been loaded (in Rails 2.3.10 anyway).
您可以使用loaded_ foo来检测单个关联是否已加载。例如,如果shipping_info 是belongs_to 关联,那么item.loaded_shipping_info? 当它被急切加载时将返回 true。奇怪的是,它似乎在尚未加载时返回 nil(而不是 false)(无论如何在 Rails 2.3.10 中)。
回答by Lev Lukomsky
Solution to this problem should be foo.association(:bla).loaded?, BUT it works incorrectly - it checks and marks association as dirty:
这个问题的解决方案应该是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
So I've added following extension to ActiveRecord:
所以我在 ActiveRecord 中添加了以下扩展:
module ActiveRecord
class Base
def association_loaded?(name)
association_instance_get(name).present?
end
end
end
and now:
现在:
class Foo; has_one :bla, :autosave => true end
foo.association_loaded?(:bla) #=> false
foo.save # saves foo
回答by Bitterzoet
Have a look at the Bullet gem.. This will tell you when you should and should not use eager loading.
看看子弹宝石。. 这会告诉你什么时候应该和不应该使用预先加载。

