2010-11-14 12 views
19
  1. métodos de asociación hacen, como los definidos por has_many y belongs_to utilizan ActiveRecord::Relation?¿Es posible conseguir el objeto ActiveRecord :: Relación de una asociación

  2. Si es así, ¿es posible obtener el objeto ActiveRecord::Relation que se está utilizando?

Todos somos conscientes de que Rails 3 es en gran medida utilizando ActiveRecord::Relation objetos y Arel::Relation objetos en el fondo, al crear consultas utilizando el Query Interface. Cuando utilizamos los métodos select, joins, etc. de la interfaz de consulta, se devuelve un objeto ActiveRecord::Relation. Sin embargo, este no parece ser el caso cuando se llama a un método de asociación de un modelo. En cambio, la consulta se ejecuta inmediatamente y se devuelve una instancia, o una matriz de instancias, del modelo asociado.

considerar los siguientes modelos:

post.rb

class Post < ActiveRecord::Base 
    belongs_to :user 
end 

user.rb

class user < ActiveRecord::Base 
    has_many :posts 
end 

Ejemplo:

u = User.first 
u.posts 

Llamada u.posts devuelve una matriz de publicaciones, no una instancia de ActiveRecord::Relation. Me pregunto si es posible obtener el ActiveRecord::Relation que es que está siendo utilizado por la asociación, si se está utilizando, tal vez mediante el uso de Arel::Table?

Mi razonamiento para querer ActiveRecord::Relation debe ser obvio: es porque quiero encadenar la asociación existente y manipular la consulta para un propósito diferente.

Respuesta

32

Durante unos minutos, he usado el truco where(nil), entonces tuve una idea luminosa y hemos probado algo aleatorio:

User.first.posts.scoped 

Eso es todo! : D

Sí, Rails + Arel está muy poco documentado. Esperando que madure hasta el punto en que realmente pueda buscar cosas y obtener respuestas reales.

+0

Love it. ¡Mucho más limpio! Te estoy dando el CHECKMARK. Y estoy de acuerdo con la documentación de Arel. He estado leyendo fragmentos y trozos de todo el lugar al respecto. Parece muy poderoso, pero sin una buena documentación, puede ser bastante molesto también. :) – John

+0

Brillante, muchas gracias! –

+0

¿hay alguna manera de llamar a '.scoped' en una matriz personalizada que hice? – brittohalloran

1

Al tomar el tiempo para leer realmente la documentación de Edge Guides, pude encontrar una respuesta en Section 4.3 has_many Association Reference. En resumen, la documentación no arroja luz sobre si es posible obtener el objeto ActiveRecord::Relation o si se está utilizando un objeto ActiveRecord::Relation, pero proporciona detalles sobre cómo reutilizar la asociación y adaptar su resultado.

Sección 4.3.1 Methods Added by has_many enumera el collection.where como uno de los métodos que se añade por la asociación has_many. Y la sección 4.3.1.11 collection.where(…) muestra que la usaría tal como lo haría con el método where de la interfaz de consulta. Más importante aún, da una pista de que los objetos se cargan de forma perezosa al usar este método en la colección, y de hecho se devuelve un objeto ActiveRecord::Relation.

u.posts.where("").class # => ActiveRecord::Relation 
u.posts.where("").to_sql # => SELECT `posts`.* FROM `posts` WHERE `posts`.user_id = 1 

Es cierto que no es la solución ideal, pero me da algo de lo que puedo hacer una cadena.

3

en los carriles 4, utilice .scope o .spawn para acceder al objeto relación en lugar de la CollectionProxy. Vea el documentation.

1

En un ActiveSupport::Concern, no puede llamar al método privado spawn o usar scope o scoped.

Necesitaba usar esto.

where(true) 
Cuestiones relacionadas