2011-02-09 8 views
11

Así que tengo una publicación y un usuario.
Publicación tiene muchos usuarios y un usuario pertenece a una publicación.
Necesito un hallazgo que encontrar todos los mensajes que no tenga ni los usuarios como las siguientes:encuentra todos los que son nulos en la asociación

Post.first.users 
=> [] 

Respuesta

26
Post.where("id not in (select post_id from users)") 
+0

Si la subconsulta contiene un nulo, no se devolverá nada y es posible que desee utilizar 'NOT EXISTS' en su lugar, como necesitaba en mi caso particular. [Lectura adicional] (http://stackoverflow.com/questions/173041/not-in-vs-not-exists). – manafire

1

Post.first.users.empty? debería ser suficiente si los usuarios devuelve un array.

Si desea comprobar para cada puesto que podría hacer

Post.each do |p| 
    if p.users.empty? 
    do whatever 
    end 
end 
+0

i necesidad de encontrar todos los mensajes ... no sólo la primera – Trace

+0

así que necesito algo así como Post.All (: include =>: users,: conditions => "users =?", nil) – Trace

+0

'Post.each do | p | si p.users == nil hace el extremo final' – acconrad

2

Si necesita algo que es rápido, emplean una instrucción SQL como:

SELECT * 
FROM posts p 
LEFT OUTER JOIN users u ON p.id = u.post_id 
WHERE u.id IS null 
1

supongo que un sql with in puede causar problemas de rendimiento si la tabla de la base de datos tiene muchas filas. cuidado con eso

+2

Derecha. Comience con el código más legible, asegúrelo con pruebas y luego podrá comenzar a optimizar el rendimiento. Sin pruebas, corre el riesgo de que "optimice" algunos registros por accidente. Y siempre mida el rendimiento real: la versión optimizada no siempre es la más rápida. – Arsen7

2

algo así:

p = Post.arel_table 
u = User.arel_table 

posts = Post.find_by_sql(p.join(u).on(p[:user_id].eq(u[:p_id])).where(u[:id].eq(nil)).to_sql) 
1

Sé que esto es etiquetado como carriles 3, pero si usted está utilizando los carriles 4, que he estado haciendo así.

Post.where.not(user_id: User.pluck(:id)) 
14

Learned éste sólo hoy:

Post.eager_load(:users).merge(User.where(id: nil)) 

Obras con rieles 4+ al menos.

Actualización:

En Rails 5+, puede utilizar left_joins lugar:

Post.left_joins(:users).merge(User.where(id: nil)) 
Cuestiones relacionadas