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'
bundle install
2. Then run the migrations that comes with the gem.
rails g acts_as_votable:migration
rails db:migrate
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 %>
Final Thoughts
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.
1 thought on “Adding Upvotes & Downvotes in your rails app”