views:

68

answers:

2

Hi,

I have a model that has ratings in it for an post.

I want to display a list of the top 5 ratings for a given post, but I am completely lost on where to start. I figure the find method might have something useful, but I'm unsure. I've even considered looping through each record getting its size, adding it to a hash, sorting the hash, etc., but that seems too complicated.

Does anyone know how I might accomplish something like this?

Thank you

Edit: I found this to get all the posts that have the rating of agree:

Post.find(:all, :include => :post_ratings, :condtions => ['post_ratings.agree = ?', true])

The only problem is I can't figure out how to get the top five ratings from this query.

A: 

Might be worth giving a little more of an example of the code you're working with but I'll answer with a few assumptions.

If you have:

class Post
  has_many :post_ratings
end

class PostRating
  belongs_to :post

  # Has a 'rating' attribute
end

You can find the top five post ratings with:

p = Post.find(:first) # For example
p.post_ratings.find(:all, :limit => 5, :order => 'rating desc')

To get the top five post ratings overall you can do:

PostRating.find(:all, :limit => 5, :order => 'rating desc')

UPDATE:

Following your edit it seems you have an 'agree' and a 'disagree' column. Not sure how that works in combination so I'll stick with the 'agree' column. What you'll need to do is count the ratings with agree flagged. Something like:

count_hsh PostRating.count(:group => 'post_id', 
                           :order => 'count(*) desc', 
                           :conditions => { :agree => true },
                           :limit => 5)

This will return you a hash mapping the post id to the count of agree ratings. You can then use that post_id to locate the posts themselves. The ratings are provided by the counts so the individual ratings are (I think) of no use though you could access them by calling post.post_ratings.

So, to get the top five posts:

@top_five_posts = []
count_hsh.each_pair do |post_id, ratings|
  p = Post.find(post_id)
  p[:rating_count] = ratings
  @top_five_posts << p
end

This is probably more verbose than it could be but is hopefully illustrative. The p[:rating_count] is a virtual attribute which isn't in the database but will allow you to access the .rating_count method on the posts in your view if you wish to.

Shadwell
that works nice, but I want to get the top five ratings for all posts as a whole. Any idea?
Brian
I've updated my answer to include that too.
Shadwell
I guess I should clarify that the rating is actually to separate Boolean columns. The are agree and disagree.
Brian
Heh, yes, that would have been useful to know! I'll update my answer.
Shadwell
so that returns a hash? I would have to pull the key up to do a search for the post? I need display the post, which are the highest rated. I think were almost there lol.
Brian
Yes, I've edited the answer to give an example of how to do that.
Shadwell
It works! Thank you so much!
Brian
Excellent. Glad you got there in the end.
Shadwell
A: 

Assuming the same Post and PostRating from Shadwell's answer:

class Post
  has_many :post_ratings
end

class PostRating
  belongs_to :post

  # Has a 'rating' attribute
end

To get the top five ratings for all Posts:

post_ratings.find(:all, :limit => 5, :order => 'rating desc')

To get the top five ratings for a specific Post you can:

p = Post.find(:first)
post_ratings.find_all_by_post_id(p.id, :limit => 5, :order => 'rating desc')

To find all posts sorted by average rating, you can use ActiveRecord::Calculations.

PostRating.average(:rating, :group => :post_id, :include => :post, :order => 'average desc')
marshally
I think things have got slightly muddled here. You're using `post_ratings` without a reference to `p` to get all ratings (I think you want `PostRating`). Then for the specific post's post ratings you're doing `find_all_by_post_id` which is unnecessary as `p.post_ratings.find` will already just find those post ratings that are associated with the given post, and you need to call `p.post_ratings` not `post_ratings` on its own.
Shadwell