The Acts As Votable Gem
We can add likes/dislikes like youtube or upvotes/downvotes like reddit with a gem called ‘acts_as_votable’. This gem provides an easy process to add a voting functionality in your app. With this gem we can add upvote/downvote buttons and also count the number of upvotes/downvotes and display them easily.
Github Link: https://github.com/ryanto/acts_as_votable
How To Do It ?
Now, lets get started with adding a voting functionality in our app. To do it, follow the steps below
1. Add the acts as votable gem to your Gemfile and run bundler.
#File: Gemfile gem 'acts_as_votable'
2. Then run the migrations that comes with the gem.
rails g acts_as_votable:migration
This will generate a new table with the following columns.
3. To make your model votable, add acts as votable to your model. For example: this is my book model. Please note that i used devise to add authentication to my app, and also i associated the user model with my book model.
#File: app/models/book.rb class Book < ApplicationRecord acts_as_votable belongs_to :user end
4. Now add a two new methods in your controller, to call for the upvotes and downvotes.
#File: app/controllers/books_controller.rb class BooksController < ApplicationController #...Other methods def upvote unless signed_in? redirect_to new_user_session_path else @book = Book.find(params[:id]) @book.liked_by current_user redirect_to @book end end def downvote unless signed_in? redirect_to new_user_session_path else @book = Book.find(params[:id]) @book.downvote_from current_user redirect_to @book end end #...Other methods end
5. Now, In your routes file, add the following methods to call for upvotes and downvotes from your views.
#File: config/routes.rb Rails.application.routes.draw do resources :books do member do put "like", to: "books#upvote" put "dislike", to: "books#downvote" end end end
6. Now in your views, you can add the number of upvotes/downvotes or likes/dislikes that the record currently has. And you can add buttons to peform those actions, you can customize the look of the buttons later, but here i kept it very simple, with just the bare bones.
#File: app/views/books/show.html.erb #.....For Upvotes and Downvotes do this..... <p>Upvotes <%= pluralize(number_to_human(@book.get_upvotes.size), 'Upvote') %></p> <%= link_to "Upvote", like_book_path(@book), method: :put %> <p>Downvotes <%= pluralize(number_to_human(@book.get_downvotes.size), 'Downvote') %></p> <%= link_to "Downvote", dislike_book_path(@book), method: :put %> #....Or For Likes and Dislikes do this.... <p>Upvotes <%= pluralize(number_to_human(@book.get_upvotes.size), 'Likes') %></p> <%= link_to "Like", like_book_path(@book), method: :put %> <p>Downvotes <%= pluralize(number_to_human(@book.get_downvotes.size), 'Dislike') %></p> <%= link_to "Dislike", dislike_book_path(@book), method: :put %>
So, as i said earlier; this gem provides an easy way to add voting functionality to your app, there are also other features that comes with this gem, which i haven’t discussed(features like restricting a single vote to a single IP address). Please visit the gem’s page on github for a complete guide. And we can also build an entire voting functionality from scratch, in my upcoming posts, i’ll show you how to do that.