20

と の違いが気にActiveRecord::Associations::CollectionProxyなりActiveRecord::AssociationRelationます。

class Vehicle < ActiveRecord::Base
  has_many :wheels
end

class Wheel < ActiveRecord::Base
  belongs_to :vehicle
end

だから私がするなら:

v = Vehicle.new

v.wheels # => #<ActiveRecord::Associations::CollectionProxy []>

v.wheels.all # => #<ActiveRecord::AssociationRelation []>

それらの違いは何なのか、なぜこれがこのように実装されているのかわかりませんか?

4

2 に答える 2

22

ActiveRecord::Relationクエリに変換されて実行される前の単純なクエリ オブジェクトでCollectionProxyあるのに対して、もう少し洗練されたオブジェクトです。

まず、関連拡張を取得します。おそらく、このようなものを見たことがあるでしょう。多くの本を扱う書店モデルを想定します。

class Store < ActiveRecord::Base
  has_many :books do
    def used
      where(is_used: true)
    end
  end
end

このようにして、次のような構文を使用して店舗で古本を呼び出すことができます

Store.first.books.used

しかし、これは最も基本的な使用方法です。コレクション プロキシで公開されている属性ownerを使用できます。reflectiontarget

オーナー

owner、関連付けを保持する親オブジェクトへの参照を提供します

反射

reflectionオブジェクトは のインスタンスでありActiveRecord::Reflection::AssocciationReflection、関連付けのすべての構成オプションが含まれています。

目標

target関連コレクション オブジェクト (またはhas_oneとの場合は単一オブジェクトbelongs_to) です。

これらの方法を使用すると、関連付けの拡張でいくつかの条件を実行できます。たとえば、ブログがある場合、削除されたすべての投稿へのアクセス権を管理者であるユーザーに付与します (私が知っている下手な例)

Class Publisher < ActiveRecord::Base
  has_many :posts do
    def deleted
      if owner.admin?
        Post.where(deleted: true)
      else
        where(deleted: true)
      end
    end
  end
end

resetまた、との2 つのメソッドにアクセスすることもできます。最初のメソッドreload( reset) はキャッシュされた関連オブジェクトをクリアし、2 番目のメソッド ( reload) はより一般的でありreset、関連オブジェクトをデータベースからロードするために使用されます。

CollectionProxyこれが、クラスを持つことがいかに役立つかを説明してくれることを願っています

于 2015-11-13T19:05:57.273 に答える
14

Ok。違いは非常に簡単です。

あなたの例に基づく説明:

の関連付けプロキシにv.wheelsは次のものがあります。

  • v@owner としてのオブジェクト。
  • @target としての車輪のコレクション。
  • @reflection オブジェクトは:has_manyマクロを表します。

ドキュメントから:

Active Record のアソシエーション プロキシは、@owner と @target の間の仲介者です。 @target オブジェクトは、必要になるまでロードされません。

v = Vehicle.new
v.wheels # we are not sending any methods to @target object (collection of wheels)
# => #<ActiveRecord::Associations::CollectionProxy []>

つまり、 @target オブジェクト (wheelsこの場合は のコレクションを保持する) でメソッドを呼び出すとすぐに @target が読み込まれ、 になりActiveRecord_AssociationRelationます。

v.wheels.all # sending the `all` method to @target (wheels)
# => #<ActiveRecord::AssociationRelation []>
于 2015-11-13T18:09:08.977 に答える