Tipo de retorno de una consulta de ActiveRecord
Frecuentes
Visto 4,111 veces
4
¿Qué me permitirá saber si obtendré una relación, una matriz o algún otro tipo de una llamada de ActiveRecord? Sé que puedo escribir .class en la consola y resolverlo, pero ¿hay algo en la llamada que me permita saber lo que estoy pidiendo?
2 Respuestas
2
Sabes, Rails a veces te miente, todos los magos lo hacen :)
Rails le permite crear consultas complejas encadenando sus has_many
asociaciones. El núcleo de esta funcionalidad es un montón de XXXAssocation (como HasManyAssociation
) clases. Cuando usted llama .class
en un has_many
asociación su convocatoria se aplica de hecho para HasManyAssociation
ejemplo. Pero aquí está la magia comienza:
# 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 (oculta) métodos de HasManyAssociation
instancia (excepto las pocas, como puede ver en la expresión regular) y luego usa delegación y method_missing
para pasar su llamada a una matriz subyacente (si está tratando de obtener registros) o a la asociación en sí (si está encadenando su asociación):
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
¿Entonces HasManyAssociation
instancia decide qué manejar por sí mismo y qué debe lograrse a través de una matriz oculta (class
método no es lo que HasManyAssociation
interesado, por lo que se llamará en esta matriz oculta. El resultado, por supuesto, será Array
, que es un pequeño engaño).
contestado el 03 de mayo de 12 a las 12:05
1
Aquí está mi percepción, en la línea de lo que creo que es importante saber. Es principalmente de memoria y de mi cabeza con un poco de experimentación con la consola, así que estoy seguro de que si esto se transmite, podría mejorarse. Comentarios bienvenidos y solicitados.
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
Así que lo importante es,
- Puede encadenar ámbitos y métodos de consulta, pero solo hasta el primero o todos. Después de primero o todo, no puede llamar a más ámbitos y métodos de consulta.
- Cuando llama a todos, obtiene una matriz de resultados. Algunos de los métodos de Array se han redefinido para actuar en la base de datos, por lo que si desea operar en la matriz devuelta, llame a to_a. Un ejemplo es el conteo, que si se llama en la Matriz de resultados consultará la base de datos para saber cuántos registros habría en la matriz si se volviera a consultar la matriz.
contestado el 03 de mayo de 12 a las 12:05
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas ruby-on-rails activerecord or haz tu propia pregunta.
Sería útil saber qué está tratando de hacer con el resultado. - ezkl