Consultas sql anidadas en rieles cuando: has_and_belongst_to_many

En mi aplicación, la siguiente tarea que aún no ha sido realizada por un usuario. Tengo tres modelos, A RESERVA que tiene muchos tareas y luego tengo un Usuario que ha tenido y pertenece a muchas tareas. La tabla tasks_users contiene todas las tareas completadas, por lo que necesito escribir una consulta compleja para encontrar la siguiente tarea a realizar.

Se me han ocurrido dos soluciones en SQL puro que funcionan, pero no puedo traducirlas a rieles, para eso necesito ayuda

SELECT * FROM `tasks`
WHERE `tasks`.`book_id` = @book_id
AND `tasks`.`id` NOT IN (
    SELECT `tasks_users`.`task_id`
    FROM `tasks_users`
    WHERE `tasks_users`.`user_id` = @user_id)
ORDER BY `task`.`date` ASC
LIMIT 1;

e igualmente sin selección anidada

SELECT *
FROM tasks
LEFT JOIN tasks_users
    ON tasks_users.tasks_id = task.id
    AND tasks_users.user_id = @user_id
WHERE tasks_users.task_id IS NULL
AND tasks.book_id = @book_id
LIMIT 1;

Esto es lo que he hecho en rieles con el complemento MetaWhere

book.tasks.joins(:users.outer).where(:users => {:id => nil})

pero no puedo averiguar cómo llevar al usuario actual allí también,

Gracias por cualquier ayuda!

preguntado el 09 de enero de 11 a las 01:01

2 Respuestas

Creo que esto duplicará el segundo formulario con LEFT JOIN:

class Task < ActiveRecord::Base
  scope :next_task, lambda { |book,user| book.tasks.\
    joins("LEFT JOIN task_users ON task_users.task_id=tasks.id AND task_users.user_id=#{user.id}").\
    where(:tasks=>{:task_users=>{:task_id=>nil}}).\
    order("date DESC").limit(1) }
end

Tenga en cuenta que en lugar de tasks_users esto usa el nombre de la tabla task_user, que es más típico de un modelo de combinación. Además, debe llamarse con:

Task.next_task(@book_id,@user_id)

Respondido el 09 de enero de 11 a las 10:01

Gracias, esto es algo como esto que se me ocurrió también. Muy feo con tanto SQL codificado pero funciona. - Godisemo

book.tasks.where("tasks.id not in (select task_id from tasks_users where user_id=?)", @user_id).first

Eso le daría la primera tarea que aún no tiene una entrada en tasks_users para el usuario actual.

Respondido el 09 de enero de 11 a las 09:01

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.