2010-07-26 12 views
7

Tengo publicaciones que los usuarios envían a otros usuarios. Hay dos modelos -: poste y: usuario, y: post tiene las siguientes asociaciones con nombre:rails find: uso de las condiciones al incluir la misma tabla dos veces a través de diferentes asociaciones con nombre

belongs_to :from_user, :class_name => "User", :foreign_key => "from_user_id" 
belongs_to :to_user, :class_name => "User", :foreign_key => "to_user_id" 

Ambos: usuario y: poste tiene columna "is_public", lo que indica que, o bien un solo puesto y/o la totalidad el perfil de usuario puede ser público o privado.

Mi objetivo es obtener una lista de publicaciones que son públicas Y cuyos destinatarios tienen perfiles públicos. Al mismo tiempo, me gustaría "incluir" tanto la información del remitente como la del destinatario para minimizar el número de llamadas de DNS. El desafío es que efectivamente estoy "incluyendo" la misma tabla dos veces a través de las asociaciones nombradas, pero en mis "condiciones" necesito asegurarme de que solo filtre por la columna "is_public" del destinatario.

no puede hacer lo siguiente porque "condiciones" no acepta un nombre de asociación como un parámetro:

Post.find(:all, :include => [ :to_user, :from_user ], 
    :conditions => { :is_public => true, :to_user => { :is_public => true }}) 

Por lo tanto, de una manera que puedo lograr esto es haciendo un adicional de "unirse" en el tabla "usuarios":

Post.find(:all, :include => [ :to_user, :from_user ], 
    :joins => "inner join users toalias on posts.to_user_id = toalias.id", 
    :conditions => { :is_public => true, 'toalias.is_public' => true }) 

¿hay una, tal vez más limpio, mejor manera de hacer esto?

Gracias de antemano

+0

¿Estás en Rails3 o aún en 2.3.x? –

+0

aún en 2.3.Me encantaría ver una solución para ambos – avioing

Respuesta

1

No he podido encontrar una solución mejor que la que originalmente mencioné en mi pregunta. Éste no depende de la forma en Rails nombres/tablas de alias al compilar una consulta y por lo tanto parece ser más limpio que las alternativas (abreviatura de usar gemas de 3 ª parte o plugins):

Post.find(:all, :include => [ :to_user, :from_user ], 
:joins => "inner join users toalias on posts.to_user_id = toalias.id", 
:conditions => { :is_public => true, 'toalias.is_public' => true }) 
1

que estaba enfrentando el mismo problema y encontré una solución después de ver la consulta SQL generada a partir de los carriles consulta, consulta SQL genera automáticamente un alias probar esto,

Post.find(:all, :include => [ :to_user, :from_user ], 
     :conditions => { :is_public => true, 'to_users_posts.is_public' => true }) 

funcionó para yo :)

0

Si está en Rails 3, eche un vistazo a squeel gem, esp si está haciendo este tipo de combinaciones complejas a menudo. O si no desea agregar una gema adicional, mire la tabla Arel en Rails 3.

0

I muy agradable para esa pregunta , porque he intentado encontrar la solución adecuada alrededor de las 2 h, así que después de usar algunos consejos anteriores, he encontrado la solución adecuada, en mi caso. Mi caso: Necesito instancias de filtro por los campos created_by_id/updated_by_id, esos campos están en cada tabla, entonces ... lo que hice Con respecto a 'Filterable' escribí el método y cuando necesité filtrar por esos campos lo usé - >

key = "# {key.pluralize} _ {#} name.pluralize.downcase .email" if% w (updated_by created_by) .include? (clave)

# in case with invoices key = 'updated_bies_invoices.email' 

results = results.eager_load (: created_by,: updated_by) .where ("# {key} =?", Value)

Cuestiones relacionadas