67

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

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

例如,假设我的商品模型中有一个 shipping_info 对象的“has_many”数组。然后:

如果项目是预先加载的,最有效的加载是:

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

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

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

但是除非我知道它是否被急切加载,否则我不知道调用哪个代码来有效地获取记录。如果我在没有急切加载的情况下使用第一种方法,那么我必须查找比必要更多的数据库记录。如果我在急切加载时使用第二种方法,那么我急切加载的对象将被忽略。

4

7 回答 7

76

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


对于 Rails < 3.1,请使用loaded_foo?.

(自 Rails 3.1 起已弃用。请参阅:https ://github.com/rails/rails/issues/472 。)

于 2011-06-07T07:19:02.237 回答
63

item.shipping_infos.loaded?会告诉你。

不过,我得说:这条路会导致疯狂......在编写测试代码以在andloaded?之间做出决定之前,请确保这个实例真的很重要,相对于正在发生的所有其他事情。#detect#find

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

于 2009-09-04T05:50:19.377 回答
26

我建议使用 item.association_cache.keys 来提供急切加载的关联列表。那么你item.association_cache.keys.include?(:name_of_association)

于 2013-02-26T21:09:44.010 回答
5

association_cached?可能很合适:

item.association_cached?(:shipping_infos)
于 2018-07-04T12:19:08.680 回答
3

您可以检测是否已使用loaded_ foo加载了单个关联?例如,如果 shipping_info 是 belongs_to 关联,那么 item.loaded_shipping_info? 当它被急切加载时将返回true。奇怪的是,当它没有被加载(无论如何在 Rails 2.3.10 中)时,它似乎返回 nil(而不是 false)。

于 2011-04-21T19:34:06.193 回答
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
于 2012-07-10T16:01:17.443 回答
1

看看子弹宝石。. 这将告诉您何时应该和不应该使用急切加载。

于 2009-09-15T14:26:51.613 回答