Implement a like feature for posts

Overview

This time, for posting apps like twitter With the ability to like and cancel, A function that can count likes and display the number of likes, I will summarize the implementation that makes the like link a heart.

By the way, regarding the function to like posts, there is a curriculum in progate, but I did not get the function I expected even if I implemented it as it is, so I searched a lot of sites such as qiita.

I will summarize it based on that as well.

Appearance of function

like-qiita.png

Implementation

Prepare a like model

rails g model like

In the migration file t.references, foreign_key: Set the user_id and post_id columns as true.

models/like.rb


class Like < ApplicationRecord
  validates :user_id, presence: true
  validates :post_id, presence: true
end

Set up routing

routes.rb


post "likes/:post_id/create" => "likes#create"
post "likes/:post_id/destroy" => "likes#destroy"

As a result, rails routes will look like the following image. Don't get this wrong, as you will need it when you specify the link in the view file.

like-routes.png

Create a controller

controllers/likes_controller.rb


class LikesController < ApplicationController
  before_action :authenticate_user!



  def create
    @like = Like.new(user_id: current_user.id, post_id: params[:post_id])
    @like.save
    redirect_to "/posts/#{@like.post_id}"
  end

  def destroy
    @like = Like.find_by(user_id: current_user.id, post_id: params[:post_id])
    @like.destroy
    redirect_to("/posts/#{params[:post_id]}")
  end


end

After saving or deleting, you will be redirected to the details page of the post.

Let's prepare a view file

views/posts/show.html.erb


<div class="like-btn">
    <% if Like.find_by(user_id: @current_user.id, post_id: @post.id) %>

      <%=link_to("/likes/#{@post.id}/destroy", {method: :post}) do %>
        <span class="fa fa-heart like-btn-unlike"></span>
      <% end %>

    <% else %>

      <%= link_to("/likes/#{@post.id}/create", {method: :post}) do %>
        <span class="fa fa-heart like-btn"></span>
      <% end %>

    <% end %>
  </div>

First, use conditional branching to branch whether the user likes or not, and then branch. Specifies whether to create or destroy when the button is pressed.

And, as I will write next, you can put an HTML sentence between them by setting link_to ~~~ do. (See progate's rails curriculum if you're not familiar with it)

Make sure you don't get the URL for link_to wrong.

As you can see in the image I put in the routing earlier, write / likes / post_id / create (or destroy).

Make a like a button with a heart icon

I don't know anything else because I referred to progate for this part. Use font-awesome to turn the links you like into buttons.

First, load the link in the head part so that you can use font-awesome.

views/layouts/application.html.erb


 ---abridgement---

  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
 </head>

The view file is already written in a suitable format, so Finally, write css so that it will be pink if you like it and gray if you do not like it.

As you can see by checking the views / posts / show.html.erb described earlier, like-btn and like-btn-unlike are separated by the like button and the cancel button.

assets/stylesheets/likes.scss


.like-btn {
  color: #8899a6;
}


.like-btn-unlike {
  color: #ff2581;
}


.posts-show-item .fa {
  font-size: 16px;
  margin-right: 3px;
}

You should now be able to like and undo with the heart button.

Finally, let's count and display the number of likes.

Count and display the number of cases

The procedure is to define @like_count in the show method of the posts controller and display it in the view file.

controllers/posts_controller.rb


def show
    @post = Post.find(params[:id])
    @comment = Comment.new
    @comments = @post.comments.includes(:user)
    @like_count = Like.where(post_id: @post.id).count
 end

We define where to search the database for likes about the post and count them by count.

views/posts/show.html.erb


<div class="like-btn">

  <h3>Number of likes:<%= @like_count %></h3>

    <% if Like.find_by(user_id: @current_user.id, post_id: @post.id) %>
      <%=link_to("/likes/#{@post.id}/destroy", {method: :post}) do %>
---abridgement---

That's it.

Recommended Posts

Implement a like feature for posts
How to implement a like feature in Rails
How to implement a like feature in Ajax in Rails
Implement something like a stack in Java
Implement the Like feature in Ajax with Rails.
About adding a like function
Implement a refined search function for multiple models without Rails5 gem.