paint-brush
Integrating a Voting System into Your Blog Appby@adeshola-adewale

Integrating a Voting System into Your Blog App

by Adeshola AdewaleJuly 21st, 2020
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

This article is about adding a voting system to your blog app. We all want to allow users to show their interest and react to an article through voting and also get the article with the highest vote. The voting table will set the relationship between the vote by each user and the voted article. We will also set a uniqueness of a vote per user, this will make sure an article is voted once by a user. To create our vote controller we need to create our Votes controller by adding the following code to our app/controllers/vote.rb.
featured image - Integrating a Voting System into Your  
Blog App
Adeshola Adewale HackerNoon profile picture

This article is about adding a voting system to your blog app, where users can vote or not vote an article. We all want to allow users to show their interest and react to an article through voting and also get the article with the highest vote. So let’s get started.

Create the Voting Table

Open your rails app directory and enter the code below in your terminal to add the voting table to your database. This will set the relationship between the vote by each user and the voted article.

rails g model Vote user:references article:references

To add the migration to your schema table run

rails db:migrate
and check your schema table which is added after migrating.

Open your vote model which is located in the

app/models/vote.rb
and ensure you have the code below.

class Vote < ApplicationRecord
  belongs_to :user
  belongs_to :article
end

Vote Count

We will use

counter_cache
to get the accumulated votes in our database. It counts the number of votes for each article I like to use it because it helps to reduce the number of database queries. We will also set a uniqueness of a vote per user, this will make sure an article is voted once by a user. Let's add a vote count to our article before adding the
counter_cache
.

rails g migration add_vote_count_to_articles

open the migration you just generated which is in

db/migrate
and add the following code to your change method then run
 rails db:migrate

class AddVoteCountToArticles < ActiveRecord::Migration[5.2]
  def change
    add_column :articles, :votes_count, :integer, null: false, default: 0
  end
end

Do not forget to complete the relationship between votes with articles and users in the user and article model and adding the code written below.

has_many :votes

Also, make sure that you have this code in your

 config/routes.rb
file

 resources :articles do
    resources :votes
  end

Adding votes uniqueness

To make sure an article is voted once by a user add the following code in your vote model, this adds 1 vote per user on an article.

 validates :user_id, uniqueness: { scope: :article_id }

At this point let us change our Vote model and add the

counter_cache
to count the number of votes on each article. Our vote model should look like this after adding it

class Vote < ApplicationRecord
  belongs_to :user
  belongs_to :article, counter_cache: true
  validates :user_id, uniqueness: { scope: :article_id }
end

Upvote and Downvote an Article

To vote we need to create our Votes controller by adding the following code

rails g controller votes create destroy

open your votes controller which is in your

app/controllers/votes_controller.rb
and add this code to upvote and downvote an article.

class VotesController < ApplicationController
  def create
    @vote = current_user.votes.new(article_id: params[:article_id])

    if @vote.save
      redirect_to articles_path, notice: 'Vote added.'
    else
      redirect_to articles_path, alert: 'You cannot vote twice.'
    end
  end

  def destroy
    @vote = Vote.find_by(id: params[:id], user: current_user, article_id: params[:article_id])
    if @vote
      @vote.destroy
      redirect_to articles_path, notice: 'You downvoted an article.'
    else
      redirect_to articles_path, alert: 'You cannot downvote an article that you did not vote before.'
    end
  end
end

Creating our vote helpers method for our view

We can easily add our voting methods in our views by creating our vote methods in our application helper in your

app/helpers/application_helper.rb 
to detect if our users have voted an article. This will be done by writing the code below.

module ApplicationHelper

 def upvote_or_downvote_btn(article)
    vote = Vote.find_by(article: article, user: current_user)
    if vote
      link_to('<i class="fa fa-thumbs-down"></i>'.html_safe,
              article_vote_path(id: vote.id, article_id: article.id), method: :delete)
    else
      link_to('<i class="fa fa-thumbs-up"></i>'.html_safe, article_votes_path(article_id: article.id), method: :post)
    end
  end
end

I added Font Awesome icon just for a visual sign that the article was upvoted and downvoted you can check here on how to add Font Awesome icons to your rails app. Now you can call this method in article views to check for votes on an article.

Display votes count

To get a visual display of your accumulated votes count add the following code in your articles view.

<%= pluralize(@article.votes.count, 'Vote') %>

Now the total number of votes for each article is visible to your users. you can also get the article with the highest by simply adding this code to your article model.

  scope :highest_vote, -> { order(votes_count: :desc) }

To get the article with the highest vote all we need is to call

highest_vote 
on our article and we get the article with the highest vote.

Conclusion

We have finally integrated a voting system to our blog app other features can be added to your blog app to improve user experience on your website. Click here for the GitHub repo for this project. Thanks for reading.