Ratyrate: Add Rating to Your Rails App

Share this article

This tutorial explores how to add rating functionality to a Rails application. It will go through some of the more popular Ruby gems that provide such functionality, as well as how to implement rating from scratch. We will use the same application used in the the Online store article By Karim El Hussieny, in which the basic application creation process is explained in detail. Please refer to that post to learn how Karim scaffolded and styled the basic application.

Here is the fork of the repository that we will use for our application.

Goals

As you can see in the repository, it is an online store for movies. We need to add rating functionality to each movie. Each user will be able to give a rating to the available movies. Then, each movie will have a score calculated based on all the user rating, much like what IMDB does.

Main Features

  • Rating movies: Rating the available store movies. (Login required)
  • Show user rating: Each user can visit his/her dashboard and see the movies (s)he rated. The ratings can be changed at anytime.
  • Change star numbers Star numbers can be set to whatever suits the application nature.
  • Show the score in digits Rating score can also be viewed as digits beside the stars.
  • Movie overall average score: Each movie has a score based on all the user ratings. This score is calculated from all the dimensions of the movie, i.e. visual effects, custome design, etc.
  • Ability to disable rating Rating can be disabled after the first rate and changed to readonly mode.
  • Customizable icons Star and cancel icons can be changed.
  • Canceling rating: User can cancel the rating given to any movie at any time.

Skills Needed

  • Experience with Ruby on Rails.
  • Basic knowledge of HTML/CSS3.
  • Understanding the concept of responsive CSS frameworks.

Tools

  • Ruby (2.1.0) – Programming language
  • Rails (4.1.1) – Back-end framework
  • Foundation 5 – Front-end CSS framework
  • Ratyrate – Ruby gem
  • Devise – User authentication

Ratyrate Gem

Ratyrate is a Ruby gem that wraps the functionality of the Raty jQuery plugin. It also adds some helpers along the style of IMDB rating. I forked it from a gem called Letsrate because of Letsrate’s inactivity. Ratyrate has some awesome, new features, so you are welcome to star it :)

Step 1: Installation of Ratyrate gem

To install this Ruby gem simply include it in your Gemfile like so:

gem 'ratyrate'

In the terminal run:

bundle install

You may want to watch the repository and use the development version of Ratyrate because I am adding new features all the time. To use the development gem add the following to your Gemfile:

gem 'ratyrate', :github => 'wazery/ratyrate', :branch => 'development'

Step 2: Preparing the Application

I assume you have already cloned the moviestore repository and are inside its directory. If you don’t know how to do that, here is the commands:

$ git clone 'git@github.com:wazery/moviestore.git'
$ cd moviestore

Now you need to run the gem’s generator to copy the required assets and files (jQuery Raty plugin files, star icons, and JavaScript files) to their correct locations in your Rails application. In the terminal run:

$ rails g ratyrate User

As you can see, this command takes a single argument: the name of your existing Devise user model. This is necessary to bind the user and rating data.

Output files:

create  app/assets/javascripts/jquery.raty.js
create  app/assets/images/star-on.png
create  app/assets/images/star-off.png
create  app/assets/images/star-half.png
identical app/assets/images/mid-star.png
identical app/assets/images/big-star.png
create  app/assets/images/cancel-on.png
create  app/assets/images/cancel-off.png
create  app/assets/javascripts/ratyrate.js.erb
create  app/controllers/rater_controller.rb
create  app/models/rate.rb
create  app/models/rating_cache.rb
create  app/models/average_cache.rb
identical app/models/overall_average.rb
 route  post '/rate' => 'rater#create', :as => 'rate'
create  db/migrate/20140814135421_create_rating_caches.rb
identical db/migrate/20140706144643_create_rates.rb
create  db/migrate/20140814135422_create_average_caches.rb
create  db/migrate/20140814135423_create_overall_averages.rb

Run the migrations created with this generator, which create the required tables for the rating functionality. To run the migration:

$ rake db:migrate

Example

Suppose you have a Devise user model named User. The Devise generator and ratyrate generator then look like:

$ rails g devise:install
$ rails g devise user

$ rails g ratyrate user # => user is the model generated by devise

This generator will create Rate and RatingCache models linked to your User model. In our case, however, you don’t need to run the Devise generators as the moviestore repository has done that already.

Step 3: Add the ratyrate Associations

Open the Movie model, or whatever model you want to add the starring capabilities to, and add the following line:

ratyrate_rateable 'visual_effects', 'original_score', 'director', 'custome_design'

This adds some dimensions which the user can rate. Here, we added four dimensions. This line also creates the required associations.

You also need to define the model that will do the actual rating. For our MovieStore application, it is the User model, so add the following line to it:

ratyrate_rater

This also adds the required association to the User model.

Step 4: Using the Ratyrate Helper in Views

Open up the “show” view of the movies, which you can find in app/views/movies/show.html.erb

<div class="row">
  <div class="small-2 large-2 columns">
    <%= imdb_style_rating_for @movie, current_user%>
  </div>
  <br>
  <div class="small-2 large-4 columns">
    <% if current_user %>
      Visual Effects: <%= rating_for @movie, "visual_effects" %>
      <br>
      Original Score: <%= rating_for @movie, "original_score" %>
      <br>
      Director: <%= rating_for @movie, "original_score" %>
      <br>
      Custome Design: <%= rating_for @movie, "custome_design" %>
    <% end %>
  </div>
</div>

The view uses the provided rating_for helper to show the rating for each dimension that was specified.

Step 5:** Explore the rating_for Options

Here is how this view currently looks:

1

As you can see, the user can cancel the rating. This feature can be disabled, as we will discover later.

Stars

The number of stars can be changed by simply using the option stars:

Visual Effects: <%= rating_for @movie, "visual_effects", stars: 10 %>

1

Disable/Enable Rating

By default, after the user provides a rating the stars are disabled. However, there is an option to let it remain enabled so the user can change the rating. This option is disableafterrate, which is set to true by default. Set it to false as follows:

Visual Effects: <%= rating_for @movie, "visual_effects", disable_after_rate: false %>

Now the stars will not be disabled after the user’s first rating.

Half Stars

Once there are several ratings, it is likely that the average score will have half stars and, thus, be half-highlighted. This is the default behavior, but if you want to disable half stars, use the half_show option:

Visual Effects: <%= rating_for @movie, "visual_effects", half_show: false %>

Rating with More Precision

There is a useful option in which user can rate using half values, which is disabled by default. To enable it, just use this option:

Visual Effects: <%= rating_for @movie, "visual_effects", enable_half: true %>

1

Customizing Star Icons

One of the most useful options in this helper is to customize the icons of the stars. The provided icons include:

  • Disabled stars (star_off)
  • Enabled stars
  • Half stars
  • Cancel button in off state
  • Cancel button in clicked state

You can customize each icon using its specific option, or just change the path to other icons with the same name.

Here is how to change the path:

Visual Effects: <%= rating_for @movie, "visual_effects", path: 'star_icons' %>

And here is how to change each icon separately:

  • star_on
  • star_off
  • star_half
  • cancel_on
  • cancel_off

1

Changing the Position of the Cancel Button

The Cancel button is shown on the left, by default. You can change that to the right if you want:

Visual Effects: <%= rating_for @movie, "visual_effects", cancel_place: 'right' %>

1

Adding a Hint to Cancel Button

There is an option to add a custom hint message to the cancel button. The default message is “Cancel current rating!”:

Visual Effects: <%= rating_for @movie, "visual_effects", cancel_hint: 'Cancel this vote!' %>

1

Space Between Stars

You can turn the spacing between stars on/off easily by:

Visual Effects: <%= rating_for @movie, "visual_effects", space: true %>

It is false by default.

1

Getting Average Score

One of the new options I have added to this gem is the IMDB style average. It is a bit tricky to enable, as you need to enable two options (disable_after_rate, and imdb_avg):

Original Score: <%= rating_for @movie, "original_score", disable_after_rate: true, imdb_avg: true %>

The stars will change to display the average rating score using IMDB style stars after page refresh.

1

Displaying Score Hint

You can display score hints (bad, poor, regular, gorgeous) or the cancel hint in a custom div, instead of showing them in tooltips:

Original Score: <%= rating_for @movie, "original_score", target: '#hintDiv' %>
<div id="hintDiv"></div>

As you can see, “hintDiv” is selected by its ID. It is not just limited to divs, as you can set the target to text fields, text areas, or select boxes.

1

Add Text to the Hint

You can set a placeholder text to the target div (custom div you selected):

Original Score: <%= rating_for @movie, "original_score", target: '#hintDiv', targetText: 'Some text goes here!' %>

1

Changing the Type of Target Text

You can display some hints (bad, poor, etc) or just the score numbers. To change that, you have two options:

The default one which is “hint”:

Original Score: <%= rating_for @movie, "original_score", target: "#hintDiv", targetType: "hint" %>

And the score values:

Original Score: <%= rating_for @movie, "original_score", target: "#hintDiv", targetType: "score" %>

1

Changing the Format of Target Text

What if you want to display the hints or score values with a custom format, like “Score: 5” or “Rating: Good”? It is very simple, just look at these two examples:

Original Score: <%= rating_for @movie, "original_score", target: "#hintDiv", targetFormat: "Score: {score}" %>

1

Original Score: <%= rating_for @movie, "original_score", target: "#hintDiv", targetFormat: "Rating: {hint}" %>

Rating for User Helper

It would be nice to see the rating score of the current user so it can be changed. There is a helper named ratingforuser for that exact purpose. It takes the rateable object (the movie object in our application case), the current logged in user (provided by Devise), the dimension in which the rating is for, and the options. If the current user hasn’t provided a rating yet, it will display a single star. If the gave a rating of 2, for example, it displays two stars, that can be changed to one, meaning, the user cannot raise the given score.

Here is how to use it:

Visual Effects: <%= rating_for_user @movie, current_user, "visual_effects" %>

1

IMDB Style Rating Helper

Another useful helper is an overall average score of all dimensions, just like the IMDB. This helper is pretty easy to use, just pass in the rateable object (which is the movie in our application) and the current logged in user:

<%= imdb_style_rating_for @movie, current_user %>

1

Summary

In this tutorial, the Ratyrate gem added rating functionality to the movies in the MovieStore application. We explored how to use the Ratyrate gem in detail, and the available helpers and options in it. I hope this tutorial rates highly with you today!

Islam WazeryIslam Wazery
View Author

Islam is a freelance web developer with experience spanning the full stack of application development. He is a co-founder of Whitespace which is a web development agency. Besides for that he spends his time working on open source projects that he find intriguing or writing tutorials. He was an ex-Google Summer of Code student in 2012 and a mentor for 2 projects in 2013 for KDE. You can find him on Twitter @wazery_ or check his Linkedin profile linkedin.com/in/wazery.

GlennG
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week