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…

Related posts:

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


23 Responses to “Acts As Rateable Plugin”

  • Anand Says:

    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

  • Zach Says:

    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

  • Sean Says:

    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?

  • TechKnow Says:

    @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. :(

  • Daniel Fischer Says:

    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!

  • Daniel Fischer Says:

    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?

  • TechKnow Says:

    @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.

  • Shawn Says:

    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!

  • TechKnow Says:

    @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.

  • Ivan Storck Says:

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

  • Ivan Storck Says:

    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
    
  • Seth Says:

    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

  • Flvorful Bloggage : New Rails Plugin - Acts As Noteable Says:

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

  • David Lowenfels Says:

    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

  • Lukas Says:

    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”

  • Dom Says:

    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?

  • Dom Says:

    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

  • TechKnow Says:

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

  • kyanh Says:

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

  • Rails Plugins Recommendations Says:

    [...] 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. [...]

  • plug in ??????????????????????? Ruby on Rails « Neokain on Rails Says:

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

  • links for 2008-03-31 « Web Flakes Says:

    [...] 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) [...]

  • Thomas Olausson » Blog Archive » find items not rated or created by user Says:

    [...] 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 [...]

Leave a Reply