Question

Lets say I have the following DataMapper resources:

class Post
  include DataMapper::Resource 

  has n, :comments
  ...

end  

class Comment
  include DataMapper::Resource 

  belongs_to :post
  ...

end

To get the ordered list of posts, I know you can do:

@posts = Posts.all(:order => :date.desc)

But lets say I want to display all the Posts ordered descending by how many comments they have. How would I do that?

Was it helpful?

Solution

A good way to do this for performance reasons is to cache the comment_count value for the post, which would then give you an attribute to use for the :order, maybe like :order => :comment_count_cache.desc . This is easily setup by adding an after creation hook for the Comment model.

OTHER TIPS

You can alternatively use sort_by, which calls a separate query:

@post = Post.all(:order => :date.desc).sort_by { |post| -post.comments.count }

If you want to change the order, you can take out the minus sign:

@post = Post.all(:order => :date.desc).sort_by { |post| post.comments.count }

This is nice syntactically, but like adamaig points out, it'll probably perform worse than caching the number of comments in the db because you are adding an additional SQL query.

I believe that the SQL you want to generate is:

SELECT posts.*, COUNT(comments.id) AS comments_count FROM posts
JOIN comments ON posts.id = comments.post_id
GROUP BY posts.id ORDER BY comments_count DESC

As far as I know, this isn't something you can do programmatically with the Query class. Just drop into SQL for this.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top