简体   繁体   中英

Possible to order by the count of an association in active record?

Lets say I have Posts with many Comments

Is it possible to do an ActiveRecord query to to get the Posts ordered by most comments?

I'm surprised this relatively common query in plain old MySQL doesn't seem to have an easy answer in AR. Yes you can use a counter_cache, but this isn't really recreating the original query.

What am I missing?

Taking it one step further. What if Posts have many Comments which have many Likes . Is it possible to get Posts with the most Likes in aggregate?

Thanks!

As you say, counter_cache seems to be the closest to doing it the "rails way". So far I have not encountered any AR defined methods for this specific purpose but this is the closest thing to it that I have seen:

@posts = Post.select("posts.*, COUNT(comments.id) AS count_comments").joins("LEFT OUTER JOIN comments ON posts.id = comments.post_id").group("posts.id").order("count_comments DESC")

@posts.each do |post|
  puts "Comments: #{post.count_comments}"
end

Custom select to include the count_comments attribute. Joins instead of include because include will override the select syntax. Custom joins syntax instead of merely :comments because otherwise it will be an inner join which will prevent posts without comments to be retrieved.

This is basically writing the entire SQL syntax yourself, but still... it works :)

Pretty sure you can do something like this as well if you want:

posts = Post.find(:all, :include => 'comments')
posts.sort { |a,b| b.comments.count <=> a.comments.count }

I supose you can do something like this using arel::

comments= Comment.arel_table
posts= Post.joins(:comments).order(comments[:id].count)

Though, I am not sure if this is the right way to do it. You will have to try it by yourself.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM