ActiveRecord 呼び出しから Relation、Array、またはその他のタイプを取得しようとしている場合、何が通知されますか? コンソールに .class と入力してそれを理解できることはわかっていますが、呼び出し自体に、私が何を求めているかを知らせる何かがありますか?
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
。これは少し欺瞞です) )。
これが私の認識であり、私が知ることが重要だと思うことに沿っています。それは主にメモリからのものであり、コンソールの実験を少し行っただけで頭のてっぺんから外れているので、これがうまくいくと改善できると確信しています。コメントを歓迎し、要求しました。
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で呼び出された場合、配列が再度照会された場合に、その配列に含まれるレコードの数をデータベースに照会します。