Wednesday, January 11, 2012

Implementing 'thumbs_up' gem in Rails application

In one of my application, i came across a feature where i needed to provide the users a option to like or dislike certain things. While searching i came across a gem called "thumbs_up" which was very easy to implement and was quiet good also. let me explain how it can be implemented :

1. Install the gem

gem install thumbs_up

2. Generate thumbs_up migration

rails g thumbs_up

it will generate an model called vote.rb and a migration file to create table.
run the migration

rake db:migrate

3.  Now set the model which acts as voter. for ex. user model will act as voter here

class User < ActiveRecord::Base
  acts_as_voter
end

4. Specify the model which can be voted. for ex. article model can be voted

class Article < ActiveRecord::Base
  acts_as_voteable
end

There can be many models which can be voted in single application not necessary it has to be only one.

5. Specify in the view


<%=link_to image_tag('thumbs_up', :border => 0), vote_for_article_articles_path(@article), :remote => true %>
<%=link_to image_tag('thumbs_down', :border => 0), vote_against_article_articles_path(@article), :remote => true %>

6. In my controller to save the vote

def vote_for_article
    @article = Article.find(params[:id])
    current_user.vote_for(@article)
    respond_to do |format|
      format.js
    end
end

the vote_for method will add a plus vote to the article by current user.

7. Other options

voter.vote_for(voteable) # Adds a +1 vote
voter.vote_against(voteable) # Adds a -1 vote
voter.vote(voteable, vote) # Adds either a +1 or -1 vote: vote => true (+1), vote => false (-1)
positive_vote_count = voteable.votes_for
negative_vote_count = voteable.votes_against

voter.voted_for?(voteable) # True if the voter voted for this object.
voter.vote_count(:up | :down | :all) # returns the count of +1, -1, or all votes
voteable.voted_by?(voter) # True if the voter voted for this object.
voters = voteable.voters_who_voted


By default a user can vote only once, if you wish to change even that can be done. you have to just remove few lines before running migration.

In vote.rb

validates_uniqueness_of :voteable_id, :scope => [:voteable_type, :voter_type, :voter_id]

and in migration 

add_index :votes, ["voter_id", "voter_type", "voteable_id", "voteable_type"], :unique => true, :name => "uniq_one_vote_only"

That's its all done and it is good to go.....

3 comments:

  1. can you help me out please, i have some questions regarding this gem here...

    http://stackoverflow.com/questions/14683182/thumbs-up-gem-thumbs-up-button-for-users

    ReplyDelete
  2. Thanks for writing this simple tutorial, it works like a charm. Good job :)

    ReplyDelete
  3. Hi, it says Could not find generator thumbs_up, any clue? Thanks!!

    Successfully installed thumbs_up-0.6.4
    1 gem installed
    Installing ri documentation for thumbs_up-0.6.4...
    Installing RDoc documentation for thumbs_up-0.6.4...

    Then I did $ rails g thumbs_up
    Could not find generator thumbs_up.

    ReplyDelete