Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails eager loading of counts?

Eager loading is nice with the include attribute

Post.find(:all, :include => :author)

I'm wondering if you can also eager load counts, like if I wanted to get the number of comments for each post, without loading all the comments themselves?

Maybe something like

Post.find(:all, :include => [:author, "count(comments)")

I suppose I could use a count_cache column. But doing it all in an include would be really beautiful, if it's possible.

Extra bonus points if someone can show how to not only get the count, but put some conditions too, like count of only posts which have been approved.

like image 441
Brian Armstrong Avatar asked Jul 24 '09 22:07

Brian Armstrong


3 Answers

they should already be loaded use

post.comments.length

I was having this same problem because I was using .count

like image 78
Christopher Avatar answered Sep 22 '22 13:09

Christopher


Building off of avaynshtok's answer, the following technique should just make 2 database calls.

# ./app/controllers/posts_controller.rb

def index
  # First load the posts
  @posts = Post.all

  # Then you can load a hash of author counts grouped by post_id
  # Rails 4 version:
  @comment_counts = Comment.group(:post_id).count
  # Rails 3 version:
  # @comment_counts = Comment.count(:group => :post_id)
end

Then in your view

<!-- ./app/views/posts/index.html.erb  -->

<% @posts.each do |post| %>
  <!-- reference the count by the post.id -->
  post_count: <%= @comment_counts[post.id] %>
<% end %>
like image 21
Ryan Avatar answered Sep 22 '22 13:09

Ryan


Try this:

Comment.count(:group => :post)

To filter by conditions:

Comment.count(:group => :post, :conditions => {:approved => true })

These will return hashes with posts as keys and the number of comments as values.

like image 38
avaynshtok Avatar answered Sep 21 '22 13:09

avaynshtok