2013-02-14 3 views
0

У меня есть следующий запрос:Есть ли способ игнорировать подзапросы, когда нет данных для возврата?

Comic.join(:publishercomics).where("publisher_id = 1 AND (rating < 5 OR rating IS NULL) AND comics.id NOT IN (:favorites)", {:favorites => User.find_by_id(current_user_id).favorites.where("top_10 = true").map(&comic_id)}) 

current_user_id устанавливается в 0, когда нет зарегистрированного пользователя, в противном случае он устанавливается на идентификатор текущего авторизованного пользователя. Я попытался это сделать, потому что я надеялся, что мне не придется писать два запроса, один из них, когда пользователь вошел в систему, а другой - нет. В целом было бы полезно иметь возможность написать запрос, который пропускает тот факт, что нет записи, и перестает пытаться присоединиться к несуществующим данным. Если бы я был написать этот SQL непосредственно, это было бы довольно легко:

SELECT c.* 
FROM comics c 
INNER JOIN publishercomics pc ON pc.publisher_id = 1 AND pc.comic_id = c.id 
WHERE comics.id NOT IN (SELECT comics_id FROM favorites WHERE user_id = current_user_id AND top_10 = true) 
AND (c.rating < 5 OR c.rating IS NULL) 

Этот вопрос может распространяться на общем случае - есть способ сделать рельсы запросы ведут себя немного больше как SQL, так что, когда часть запрос не возвращает данные, весь запрос не подлежит? Чтобы «User.find_by_id (0) .favorites» просто не возвращал записи?

ответ

1

Try:

Comic.join(:publishercomics).where("publisher_id = 1 AND (rating < 5 OR rating IS NULL) AND comics.id NOT IN (:favorites)", {:favorites => User.find_by_id(current_user_id).nil? ? [0] : User.find_by_id(current_user_id).favorites.where("top_10 = true").map(&comic_id)}) 

или

user = User.find_by_id(current_user_id) 
Comic.join(:publishercomics).where("publisher_id = 1 AND (rating < 5 OR rating IS NULL) AND comics.id NOT IN (:favorites)", {:favorites => user.nil? ? [0] : user.favorites.where("top_10 = true").map(&comic_id)}) 
+0

Эта работа, если вы используете [0] вместо []. Когда вы используете [], рельсы генерируют «videos.id NOT IN (NULL)», который не работает так, как можно было бы ожидать. Он никогда не вернет строки. Я не могу отредактировать ваше сообщение, потому что добавление 0s не соответствует требованиям. Как обычно это работает, следует ли пометить ваш ответ как правильный, даже если это не так? Я должен добавить, что я попробовал только первый пример, но второй должен работать. – William

+1

Спасибо @William, обновил ответ, как вы предложили. – shweta

0

Я нашел другой способ этот запрос может потерпеть неудачу. Если пользователь существует, но нет фаворитов, связанных с пользователем.

Сначала я пытался добавить:

User.find_by_id(like_user_id).favorites.nil? ? [0] 

так:

Comic.join(:publishercomics).where("publisher_id = 1 AND (rating < 5 OR rating IS NULL) AND comics.id NOT IN (:favorites)", {:favorites => User.find_by_id(current_user_id).nil? ? [0] : User.find_by_id(like_user_id).favorites.nil? ? [0] : User.find_by_id(current_user_id).favorites.where("top_10 = true").map(&comic_id)}) 

Но это не работает, потому что 'избранные', так или иначе не равны нулю. Я не совсем понимаю, как это работает. Поэтому вместо этого я использовал:

User.find_by_id(like_user_id).favorites.count == 0 ? [0] 

И это, похоже, сработало.

Смежные вопросы