has_ratings icon indicating copy to clipboard operation
has_ratings copied to clipboard

Add rating support to Rails apps with this plugin

has_ratings

Instalation

  1. Install the plugin with script/plugin install git://github.com/fnando/has_ratings.git

  2. Generate a migration with script/generate migration create_ratings and add the following code:

    class CreateRatings < ActiveRecord::Migration def self.up create_table :ratings do |t| t.integer :rating, :default => 0, :null => false t.references :rateable, :polymorphic => true t.references :user t.timestamps end

     add_index :ratings, :rateable_type
     add_index :ratings, :rateable_id
     add_index :ratings, :user_id
    

    end

    def self.down drop_table :ratings end end

  3. Add two columns on each model you're going to use has_ratings: ratings_count and rating

    class AddRatingToPhoto < ActiveRecord::Migration def self.up add_column :photos, :ratings_count, :integer, :default => 0, :null => false

     add_column :photos, :rating, :float,
       :precision => 3, 
       :scale => 2,
       :default => 0,
       :null => false
    
     add_index :photos, :rating
     add_index :photos, :ratings_count
    

    end

    def self.down remove_index :photos, :rating remove_column :photos, :rating

     remove_index :photos, :ratings_count
     remove_column :photos, :ratings_count
    

    end end

  4. Run the migrations with rake db:migrate

Usage

  1. Add the method call has_rating to your model.

    class Photo < ActiveRecord::Base has_ratings end

  2. Add this association on your User model:

    class User < ActiveRecord::Base has_many :ratings end

    photo = Photo.find(:first) user = User.find(:first)

    photo.rate(:user => user, :rating => 1) # => photo.rated?(user) # => true photo.ratings # => [] photo.rating! # => 0.0 (will skip rating cache) photo.rating # => will use non-cached rating attribute photo.ratings_count # => ratings count photo.find_users_that_rated # => [] photo.find_rating_by_user(user) # =>

    retrieve best rated objects (order by rating desc)

    Photo.best_rated # => []

    retrieve most rated objects (order by ratings_count desc)

    Photo.most_rated # => []

If you have has_paginate installed, you can paginate the users that rated a given item:

photo.find_users_that_rated(:page => 2)

Use this view helper to display the rating system:

<%= rating_stars photo, current_user, rate_photo_path(photo) %>

Is based on this article. You can get the stars image at http://f.simplesideias.com.br/stars.gif. The CSS you need:

ul.rating {
	width: 80px;
	height: 16px;
	margin: 0 10px 0 0;
	padding: 0;
	list-style: none;
	float:left;
	position: relative;
	background: url(../images/stars.gif) no-repeat 0 0;
}

ul.zero			{ background-position: 0 0; }
ul.zero-half	{ background-position: 0 -16px; }
ul.one			{ background-position: 0 -32px; }
ul.one-half		{ background-position: 0 -48px; }
ul.two			{ background-position: 0 -64px; }
ul.two-half		{ background-position: 0 -80px; }
ul.three		{ background-position: 0 -96px; }
ul.three-half	{ background-position: 0 -112px; }
ul.four			{ background-position: 0 -128px; }
ul.four-half	{ background-position: 0 -144px; }
ul.five			{ background-position: 0 -160px; }

ul.rating li {
	cursor: pointer;
	float: left;
	text-indent: -999em;
}

ul.rated li {
	cursor: default;
}

ul.rating li a,
ul.rating li span {
	position: absolute;
	left: 0;
	top: 0;
	width: 16px;
	height: 16px;
	text-decoration: none;
	z-index: 200;
}

ul.rating li.one a, ul.rating li.one span 		{ left:0; }
ul.rating li.two a, ul.rating li.two span 		{ left:16px; }
ul.rating li.three a, ul.rating li.three span 	{ left:32px; }
ul.rating li.four a, ul.rating li.four span 	{ left:48px; }
ul.rating li.five a, ul.rating li.five span 	{ left:64px; }

ul.rating li a:hover {
	z-index: 2;
	width: 80px;
	height: 16px;
	overflow: hidden;
	left: 0;
	background: url(../images/stars.gif) no-repeat 0 0
}

ul.rating li.one a:hover	{ background-position:0 -176px; }
ul.rating li.two a:hover	{ background-position:0 -192px; }
ul.rating li.three a:hover	{ background-position:0 -208px; }
ul.rating li.four a:hover	{ background-position:0 -224px; }
ul.rating li.five a:hover	{ background-position:0 -240px; }

NOTE: You should have a User model. Otherwise, this won't work!

Copyright (c) 2008 Nando Vieira, released under the MIT license