web-dev-qa-db-ja.com

Railsアソシエーションが熱心に読み込まれているかどうかを確認する方法は?

Railsアソシエーションが熱心にロードされているかどうかを判断する方法を知っている人はいますか?

私の状況:結果セットがあり、関連付けの1つが積極的に読み込まれる場合とそうでない場合があります。積極的に読み込まれていない場合は、ActiveRecordの検索を使用して関連付けを検索します。熱心にロードされている場合は、検出を使用します。

たとえば、アイテムモデルにshipping_infoオブジェクトの「has_many」配列があるとします。次に:

アイテムを積極的にロードする場合、最も効率的なロードは次のとおりです。

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

アイテムが積極的に読み込まれていない場合、最も効率的な読み込みは次のとおりです。

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

しかし、それが積極的にロードされているかどうかを知らない限り、レコードを効率的に取得するために呼び出すコードがわかりません。熱心に読み込まれなかったときに最初の方法を使用した場合、必要以上のDBレコードを検索する必要があります。また、2番目の方法を積極的にロードしたときに使用した場合、積極的にロードされたオブジェクトは無視されます。

50
wbharding

item.shipping_infos.loaded? 教えてくれます。

ただし、このパスは狂気につながる...をテストするコードを書く前にloaded?#detectおよび#find、このインスタンス本当にが重要であることを確認してください。

これがアプリの最も遅い処理ではない場合、コードパスを追加すると、不必要に複雑になります。わずかなデータベースの労力を浪費する可能性があるからといって、それを修正する必要があるという意味ではありません。測定可能な方法ではおそらく問題ではありません。

50
Bryan Stearns

レコードで.association(name).loaded?を使用します。


Rails <3.1の場合、loaded_foo?

(Rails 3.1。参照: https://github.com/Rails/rails/issues/472 なので非推奨です。)

57
gamov

積極的に読み込まれた関連付けのリストを提供するitem.association_cache.keysを使用することをお勧めします。つまり、item.association_cache.keys.include? :name_of_association

21
dabobert

Loaded _foo?で単一のアソシエーションがロードされているかどうかを検出できます。たとえば、shipping_infoがbelongs_to関連付けだった場合、item.loaded_shipping_info? eager-loadedの場合はtrueを返します。奇妙なことに、(Rails 2.3.10とにかく)ロードされていない場合、(falseではなく)nilを返すようです。

3
Jim Stewart

この問題の解決策は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
3
Lev Lukomsky

Bullet gem。 をご覧ください。これにより、イーガーロードを使用する必要がある場合と使用しない場合がわかります。

2
Bitterzoet

association_cached? が適切かもしれません:

item.association_cached?(:shipping_infos)
1
phil pirozhkov