Tipo de retorno de una consulta de ActiveRecord

¿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?

preguntado el 03 de mayo de 12 a las 11:05

Sería útil saber qué está tratando de hacer con el resultado. -

2 Respuestas

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

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 or haz tu propia pregunta.