67

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

私の状況:アソシエーションの1つが熱心にロードされる場合と、ロードされない場合がある結果セットがあります。熱心にロードされていない場合は、ActiveRecordの検索を使用して関連付けを検索したいと思います。熱心にロードされている場合は、detectを使用したいと思います。

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

アイテムが熱心にロードされる場合、最も効率的なロードは次のとおりです。

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

アイテムが熱心にロードされていない場合、最も効率的なロードは次のとおりです。

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

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

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?教えてくれます。

しかし、私は言わなければなりません:このパスは狂気につながります...との間でloaded?決定するためにテストするコードを書く前に、起こっている他のすべてと比較して、このインスタンスが本当に重要であることを確認してください。#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では)、(falseではなく)nilを返すように見えます。

于 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 に答える