Acts As Rateable Plugin

Continuing with my work with Ruby on Rails plugins here is my version of the acts_as_rateable plugin. Use this plugin to make your model instances be rated by users. The ratings are numeric and could be from 0 to any number you would like. Typically you can rate articles, posts, reviews, etc from 0 to 5 but this plugin does not dictate the range. To install this plugin run the following command:

script/plugin install http://juixe.com/svn/acts_as_rateable

The installation process will add several ruby files in the vendor/plugins directory. Create a new rails migration and cut and past the following self.up and self.down methods:

def self.up
  create_table :ratings, :force => true do |t|
    t.column :rating, :integer, :default => 0
    t.column :created_at, :datetime, :null => false
    t.column :rateable_type, :string, :limit => 15,
      :default => "", :null => false
    t.column :rateable_id, :integer, :default => 0, :null => false
    t.column :user_id, :integer, :default => 0, :null => false
  end

  add_index :ratings, ["user_id"], :name => "fk_ratings_user"
end

def self.down
  drop_table :ratings
end

Once you have the acts_as_rateable plugin installed you can make your ActiveRecord models act as rateable by calling the acts_as_rateable method.

class Post < ActiveRecord::Base
  acts_as_rateable
end

In your controller you can rate a post with just a few lines of code:

post = Post.find(params[:id])
rating = Rating.new(:rating => 2, :submitted => Time.new)
@post.ratings << rating

Similarly you can do this:

post = Post.find(params[:id])
post.add_rating Rating.new(:rating => 2)

And of course you can iterate through the ratings of a post by using the ratings property such as the following bit of code:

post.ratings.each { |r|
  logger << "rating value: #{r.rating} for object: #{r.rateable}\n"
}

You can also use the ratings property to get the number of ratings this post has been given.

count = post.ratings.size

And if you want to display the average rating you can use the rating function.

average_rating = post.rating

Stay tuned for more on Ruby on Rails plugins…

Enjoy. Share. Be Happy.
  • Twitter
  • Facebook
  • StumbleUpon
  • del.icio.us
  • Tumblr
  • Google Bookmarks
  • FriendFeed
  • Yahoo! Buzz
  • Reddit
  • Digg
  • HackerNews
  • Suggest to Techmeme via Twitter
  • LinkedIn
  • Ping.fm
  • Identi.ca
  • Mixx
  • Furl

Related posts:

  1. Acts As Voteable Rails Plugin
  2. Acts As Bookmarkable Plugin
  3. Acts As Commentable Plugin
  4. Acts As Taggable Plugin
  5. Acts As Versioned Plugin

This entry was posted in Ruby, TechKnow. Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

18 Comments

  1. Posted March 2, 2007 at 7:17 pm | Permalink

    Hi

    I used the rateable plugin as well. Many thanks.

    Question on the .rating method. How is the performance when you have hundreds of ratings to calculate the average? Any tips on how to make it higher performance?

    anand

  2. Zach
    Posted March 4, 2007 at 5:50 pm | Permalink

    Hey,

    I’m using your rateable plugin, and I would like to filter my results by highest rating. I can’t come up with a way to make it work. Any suggestions.

    Zach

  3. Sean
    Posted April 4, 2007 at 7:37 am | Permalink

    I can’t seem to get this to work properly, it’s the first plugin I’ve tried to install so I think my mistake might be something simple I overlooked. Whenever I add “acts_as_rateable” to my story model I get the following error on any action that uses the story model (which is just about all of them): “undefined local variable or method `acts_as_rateable’ for Story:Class”. I installed the plugin and it is present inside the vendor/plugins directory and I created the migration and ran rake on it. If I had to guess it seems like rails isn’t finding the plugin. Is there something else I need to do?

  4. Posted April 4, 2007 at 10:36 am | Permalink

    @Sean – I only get that error when I delete the plugin from a Rails application. I just installed the plugin from the SVN repository and it worked right off the bat. In your case, the spelling of the method is correct and you say the plugin is found in the app/vendor/plugins directory. Sorry, but from your description I can’t see what could be the problem. :(

  5. Posted April 11, 2007 at 8:14 pm | Permalink

    If you wouldn’t mind TechKnow, could you give me an example of a functionality of how I could have the numbers 1..5 or maybe a dropdown to send to a picture for e.g? regarding view/controller programming?

    So far I thought of something like this:

    def rate
    @picture = Picture.find(params[:id])
    @picture.add_rating Rating.new(:rating => params[:rating])
    end

    but I am not really sure what to do in the view, or where to go/modify from here.

    Thanks!

  6. Posted April 11, 2007 at 9:20 pm | Permalink

    Also, regarding the user_id, I’m not sure how to take full advantage of that.

    A picture has many users, in the rate method I showed you, how would I set the current rating to be owned by user so and so? I thought something like @picture.user_id = self.current_user.id
    would work, but then I realized it’s not for the picture, it’s for the rating, yet rating is being created with calling the model, so not sure. Any tips?

  7. Posted April 15, 2007 at 11:59 pm | Permalink

    @Daniel – Thanks for your comments. Here are three tutorials you might like… Rails 4-State Ajax & CSS Star Rating by Igvita. Rails Ajax Rating System by Naffis. CSS Star Rating Part Deux by Komodo Media.

  8. Shawn
    Posted June 7, 2007 at 11:40 pm | Permalink

    Hi, is there any way to make this plugin tally votes numerically instead, like reddit? Where users can /- votes and they can reach negative numbers?

    Thanks for the great plugin!

  9. Posted June 8, 2007 at 4:47 pm | Permalink

    @Shawn – If you want to have a /- vote like digg or reddit then you can use Acts as Voteable. That might be just what you need.

  10. Posted August 24, 2007 at 4:33 pm | Permalink

    I’m also looking for a way to get a list of things ordered by highest rating.

  11. Posted August 27, 2007 at 3:19 pm | Permalink

    Here’s the SQL I used, my things that are rateable are called “Writings”

    SELECT
      writings.id, writings.title, writings.excerpt, writings.description,
      writings.body, writings.created_on, writings.updated_on,
      writings.created_by, writings.updated_by, writings.featured,
      writings.views, avg(rating) AS avg_rating
    FROM
      writings
    LEFT JOIN ratings ON ratings.rateable_id = writings.id
    GROUP BY rateable_id
    ORDER BY avg_rating DESC
    
  12. Seth
    Posted September 6, 2007 at 4:12 am | Permalink

    Thanks for a really good tutorial!

    Just wondering if there is a method to pull the acts_as_rateable model attributes for a specific user?

    My acts_as_rateable model is Businesses, so I can call @business.ratings.each do |b| b.user.login end – this will obviously return all the users that have rated that particular business… I would like to know how to do this in reverse…

    So pull a user and get the businesses that they have rated…

    So far I have this in the users controller which will only return the business id:
    @businesses = Rating.find(:all,
    :conditions => ["user_id = ?", @user.id],
    :order => “created_at DESC”)

    Does anyone have any ideas?

    Thanks

  13. Posted December 20, 2007 at 3:12 pm | Permalink

    Anand:
    The performance of the average rating calculation can be improved greatly by using SQL instead of ruby.

    # Helper method that returns the average rating
    #
    def rating
      Rating.average( :rating, :conditions => {
        :rateable_id => self.id,
        :rateable_type => self.class.name
      })
    end
    

    Seth:
    use the find_ratings_by_user method

  14. Lukas
    Posted December 30, 2007 at 7:19 am | Permalink

    with the newer version of rails there will be an error called :
    “The :dependent option expects either :destroy, :delete_all, or :nullify (true)”
    which appears in:
    “vendor/plugins/acts_as_rateable/lib/acts_as_rateable.rb:12:in `acts_as_rateable’”

    The Line looks like this :
    “has_many :ratings, :as => :rateable, :dependent => true”

    just change the true to one of these :
    ” :destroy This destroys the associated objects”

    ” :delete_all deletes them directly from the database ”

    ” :nullify to set the keys to null”

    so the line should look somthing like this afterwards :

    “has_many :ratings, :as => :rateable, :dependent => :destroy”

  15. Dom
    Posted January 14, 2008 at 12:16 am | Permalink

    Hi, I’m getting the following error when trying to use this plugin with a model in rails 2.0.1:

    ArgumentError in MediaController#articles

    The :dependent option expects either :destroy, :delete_all, or :nullify (true)

    My model is Article, it is currently using the following plugins:
    has_self_referential_many_to_many :related
    acts_as_taggable
    acts_as_commentable
    acts_as_rateable

    If I comment out the first four plugins and leave rateable in, I still get the error. It’s currently breaking on this line:

    Library/Ruby/Gems/1.8/gems/activerecord-2.0.1/lib/active_record/associations.rb:1149:in `configure_dependency_for_has_many’

    Can you help?

  16. Dom
    Posted January 14, 2008 at 2:01 am | Permalink

    Ok just thought I’d let you know I fixed the issue by replacing the line 12 in acts_as_rateable.rb to:

    has_many :ratings, :as => :rateable, :dependent => :destroy

    The :dependent => true option on has_many association was deprecated in 1.1:

    http://weblog.rubyonrails.org/2006/4/28/associations-arent-dependent-true-anymore

  17. Posted January 15, 2008 at 2:23 am | Permalink

    @Lukas, @Dom – Thanks for the comment. I have update the plugin accordingly.

  18. Posted January 20, 2008 at 6:46 am | Permalink

    i have installed successfully acts_as_rateable. excellent plugin! keep your great work!

5 Trackbacks

  1. [...] I borrowed heavily from Acts As Rateable by Juixe [...]

  2. By Rails Plugins Recommendations on January 20, 2008 at 11:12 pm

    [...] Acts As Rateable – If you have locations you’ll need to rate them right? Chances are there’s other things on your site that need rating as well, so this cleans up some of the code for this. It’s something that could be done without a plugin, sure, but adding “acts_as_rateable” to a model is all you need to get going. [...]

  3. [...] acts_as_rateable ????????????????????? rating [...]

  4. By links for 2008-03-31 « Web Flakes on March 31, 2008 at 1:36 am

    [...] Acts As Rateable Plugin Used this Plugin in LWF but followed instructions from Dave Naffis http://www.naffis.com/2006/8/31/rails-ajax-star-rating-system (tags: star.rating plugin acts_as_rateable ajax) [...]

  5. [...] been using the acts_as_rateable plugin at a client project. On a page, we needed to show items that weren’t rated or created [...]

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*