0

Given the canonical example:

class Post < ActiveRecord::Base
  has_many :comments
end

class Comments < ActiveRecord::Base
  belongs_to :post
end

I would like to return a scope (i.e. ActiveRecord::Relation) of all the Posts that have X or fewer Comments; using either using Active Record Query Interface, Arel or something else if it solves my problem.

Pseudocode:

scope :quiet, lambda { |n| where(comments: { maximum: n }) }

I am aware that this can be done in Ruby with a simple Enumerable#select. It is preferable to be calculated on the database as in actuality there can only ever be one Model that satisfies the predicate.

tereško
  • 58,060
  • 25
  • 98
  • 150
Thomas Nadin
  • 1,167
  • 10
  • 22

2 Answers2

1

what about this scope:

scope :quiet, ->(n) { where("(SELECT COUNT(*) FROM comments WHERE post_id = `posts`.id) < ?", n) }

It will be done all database side. It is not using join, so you can actually update those post records if needed

Iuri G.
  • 10,460
  • 4
  • 22
  • 39
1

You can do something like this..

Post.joins(:comments).group("posts.id HAVING count(comments.id) > 0")

Its not quite fully arel, but it will certainly work

Alex Barlow
  • 148
  • 1
  • 7
  • Having is what I was looking for! The full arel (`.group(...).having(...)` code is extremely verbose offering little extra benefit. – Thomas Nadin Feb 27 '13 at 11:46