4

ActiveRecord 呼び出しから Relation、Array、またはその他のタイプを取得しようとしている場合、何が通知されますか? コンソールに .class と入力してそれを理解できることはわかっていますが、呼び出し自体に、私が何を求めているかを知らせる何かがありますか?

4

2 に答える 2

2

ご存知のように、Rails は時々あなたに嘘をつきます -- すべてのマジシャンはそうします :)

Rails では、has_many関連付けを連鎖させることで複雑なクエリを作成できます。この機能の核となるのは、一連の XXXAssocation (のようなHasManyAssociation) クラスです。.classたとえば、has_manyアソシエーションを呼び出すと、呼び出しが実際に適用されますHasManyAssociation。しかし、ここから魔法が始まります。

# collection_proxy.rb
instance_methods.each { |m| undef_method m unless m.to_s =~ /^(?:nil\?|send|object_id|to_a)$|^__|^respond_to|proxy_/ }

Rails はインスタンスの undefs (非表示) メソッドHasManyAssociation(正規表現でわかるように、いくつかを除く) を使用し、委譲を使用しmethod_missingて、基になる配列 (レコードを取得しようとしている場合) または関連付け自体 (関連付けをチェーンしている場合):

  delegate :group, :order, :limit, :joins, :where, :preload, :eager_load, :includes, :from,
           :lock, :readonly, :having, :pluck, :to => :scoped 

  delegate :target, :load_target, :loaded?, :to => :@association

  delegate :select, :find, :first, :last,
           :build, :create, :create!,
           :concat, :replace, :delete_all, :destroy_all, :delete, :destroy, :uniq,
           :sum, :count, :size, :length, :empty?,
           :any?, :many?, :include?,
           :to => :@association

  def method_missing(method, *args, &block)
    match = DynamicFinderMatch.match(method)
    if match && match.instantiator?
      send(:find_or_instantiator_by_attributes, match, match.attribute_names, *args) do |r|
        proxy_association.send :set_owner_attributes, r
        proxy_association.send :add_to_target, r
        yield(r) if block_given?
      end
    end

    if target.respond_to?(method) || (!proxy_association.klass.respond_to?(method) && Class.respond_to?(method))
      if load_target
        if target.respond_to?(method)
          target.send(method, *args, &block)
        else
          begin
            super
          rescue NoMethodError => e
            raise e, e.message.sub(/ for #<.*$/, " via proxy for #{target}")
          end
        end
      end

    else
      scoped.readonly(nil).send(method, *args, &block)
    end
  end

したがって、HasManyAssociationインスタンスはそれ自体で何を処理するか、および隠し配列を介して何を達成する必要があるかを決定します (classメソッドはHasManyAssociation関心のあるものではないため、この隠し配列で呼び出されます。もちろん、結果は になりますArray。これは少し欺瞞です) )。

于 2012-05-03T11:15:01.630 に答える
1

これが私の認識であり、私が知ることが重要だと思うことに沿っています。それは主にメモリからのものであり、コンソールの実験を少し行っただけで頭のてっぺんから外れているので、これがうまくいくと改善できると確信しています。コメントを歓迎し、要求しました。

Derived ActiveRecord class --> Record Instance
  find

Derived ActiveRecord class | Relation --> Relation
  where, select, joins, order, group, having, limit, offset, a scope

Derived ActiveRecord class | Relation --> Record Instance
  find

Derived ActiveRecord class | Relation --> Result Array
  all

Result Array --> Array
  to_a

重要なのは、

  • スコープとクエリメソッドを連鎖させることができますが、それは最初またはすべてまでです。結局のところ、これ以上スコープとクエリメソッドを呼び出すことはできません。
  • allを呼び出すと、結果配列が得られます。一部のArrayメソッドは、データベースで機能するように再定義されているため、返された配列を操作する場合は、to_aを呼び出します。例としてcountがあります。これは、Result Arrayで呼び出された場合、配列が再度照会された場合に、その配列に含まれるレコードの数をデータベースに照会します。
于 2012-05-03T11:00:19.717 に答える