class Article < ActiveRecord::Base
has_many :comments
scope :without_comments,
joins(<<-SQL
LEFT OUTER JOIN
(SELECT article_id
FROM comments GROUP BY article_id) AS rolled_up_comments
ON comments.article_id = articles.id
SQL
).
where("rolled_up_comments.article_id" => nil)
end
Используйте вот так:
Article.without_comments.all
Это может быть легко адаптировано для возврата статей с определенным количеством или диапазоном комментариев, например ::
class Article < ActiveRecord::Base
has_many :comments
scope :with_comment_count,
joins(<<-SQL
LEFT OUTER JOIN
(SELECT article_id, COUNT(*) AS comment_count
FROM comments GROUP BY article_id) AS rolled_up_comments
ON comments.article_id = articles.id
SQL
)
scope :with_n_comments, lambda {
with_comment_count.
where(:"rolled_up_comments.comment_count" => n)
}
end
В последнем случае n
может быть определенным числом, таким как 100, или диапазоном, таким как 1..10
, который ActiveRecord превратит в BETWEEN
запрос, возвращающий статьи с комментариями от 1 до 10.
Обратите внимание, что в случае с 0 комментариями счетчик равен NULL
, поэтому вы не можете использовать запрос диапазона для этого.
Я проверял это в Postgres. Я не знаю, будет ли это работать в MySQL. Я не уверен, как / если MySQL обрабатывает подвыборы для объединений.
Редактировать: Решение , указанное предыдущим комментатором, проще, если вам нужно знать только статьи без комментариев. Для диапазонов подсчета будет работать вышеуказанное.