Christian Fazzini
Christian Fazzini

Reputation: 19723

How do I get all articles with 0 comments?

An article has 1 or many comments. How would I get only the articles with 0 comments?

This would be easier with a counter cache. However, I need to do this without using a counter cache.

Upvotes: 1

Views: 66

Answers (2)

Wolfram Arnold
Wolfram Arnold

Reputation: 7273

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

Use like this:

Article.without_comments.all

This could easily be adapted to return articles with a specific number or range of comments, e.g.:

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 

In the latter case, n can be a specific number, like 100, or a range like 1..10 which ActiveRecord will turn into a BETWEEN query returning articles with 1 through 10 comments.

Note that in the 0-comment case, the count is NULL, so you can't use the range query for that.

I've tested this in Postgres. I don't know if it'll work in MySQL. I'm not sure how/if MySQL handles sub-selects for joins.

Edit: The solution pointed out by a previous commenter is easier, if you only need to know articles without comments. For count ranges, the above will work.

Upvotes: 1

Alpha Beta Charlie
Alpha Beta Charlie

Reputation: 841

I'm interested by the answer.

Did you try with a scope?

I'm not sure but it could be the solution.

Rails doc : http://guides.rubyonrails.org/active_record_querying.html#scopes

Upvotes: 0

Related Questions