So you’ve got the Ajax CSS Star Rating System with acts_as_rateable (A MUST READ). Now you want to list the top rated objects and how many votes they’ve received. Fortunately Ruby on Rails and ActiveRecord makes this fairly easy by using an object’s find method.
Code
@TopRatedCampaigns = Campaign.find(:all,
:select => “campaigns.*, avg(ratings.rating) AS rating, count(ratings.rating) AS votes”,
:joins => “LEFT JOIN ratings ON campaigns.id = ratings.rateable_id”,
:conditions => “ratings.rateable_type = ‘Campaign’”,
:group => “ratings.rateable_id”,
rder => “rating DESC, votes DESC”,
:limit => 5)
Next in your view you will simply want to loop through each item and display it as a list:
< % unless @TopRatedCampaigns.nil? -%>
Top Rated Campaigns
-
< % @TopRatedCampaigns.each do |x| -%>
- < %= link_to h(x.name), campaign_url(:id => x._id) -%> (< %= number_with_precision(x.rating, 1) -%>)
< % end -%>
< % end -%>
Note: the campaign_url is defined in the config\routes.rb. This is optional, but I like using named routes in case you ever decide to change from using Rails standard routing. It’s also less code and a little cleaner than listing out the controller, action, and id.
map.campaign ‘campaign/:id’, :controller => ‘campaigns’, :action => ‘show’
Results
Based on today’s stats here are the top rated campaigns from Obsidian Portal:
Top Rated Campaigns
- Kensing (5.0)
- Arkanopolis (5.0)
- Hoarding Knowledge (5.0)
- Marvel 1984 (4.3)
- Beeropia (3.0)
Issues
The issue with this current example is if someone sets up a new campaign and rates it a 5 it will be at the top of the list even though a campaign with a 4.8 rating and 20 votes should probably be at the top of the list.
One solution would only allow campaigns with more that 5 votes to be displayed. This would be accomplished by changing the conditions in the find method. Another solution would be to somehow normalize the ratings per vote. I have not implemented either of these yet, but any feedback would be greatly appreciated.
References
Props to Patrick Crowley at moko.labs for his help with the setting up the find method.
May 25th, 2007 at 9:13 pm
Five votes might be too high of a limit.
I’d start by hiding campaigns with one vote — that will exclude the campaign creator. Then you can increment the limit based on what feels right for your app.
Smaller apps might be better with two or three, while five or more votes might make sense for bigger projects.
February 24th, 2008 at 4:27 pm
To me it is necessary to find