Railsでいいね機能を実装する方法


Railsでいいね機能を実装する方法をご紹介いたします。
完成系は以下のような感じです。

環境

  • Ruby 2.5.7
  • Rails 5.2.4

前提

  • deviseによるログイン機能が実装できていること
  • ユーザーのテーブルは"users"、記事のテーブルは"posts"、いいねの中間テーブルは"likes"とする。
  • postsのカラムはtitleを追加する

Likeモデルを追加

$ rails g model like user_id:integer post_id:integer

$ rails db:migrate

アソシエーションを設定

それぞれ以下を記述し、アソシエーションを設定します。

like.rb
  belongs_to :user
  belongs_to :post
user.rb
  has_many :likes, dependent: :destroy
post.rb
  has_many :likes, dependent: :destroy

ルーティングを設定する

routes.rb
  resources :posts, shallow: true do
    resources :likes, only: [:create, :destroy]
  end

liked_by?メソッドを作成

post.rb
  def liked_by?(user)
    likes.where(user_id: user.id).exists?
  end

controllerの記述

likes_controller.rb
  def create
    like = Like.new(user_id: current_user.id, post_id: params[:post_id])
    @post = like.post
    like.save
    redirect_back(fallback_location: posts_path)
  end

  def destroy
    like = Like.find(params[:id])
    @post = like.post
    like.destroy
    redirect_back(fallback_location: posts_path)
  end

Bootstrapを導入

Gemfile
gem 'bootstrap-sass', '~> 3.3.6'
gem 'jquery-rails'
$ bundle install

application.cssのファイル名をapplication.scssに変更する

$ mv app/assets/stylesheets/application.css app/assets/stylesheets/application.scss

Bootstrapをscssに読み込ませる

application.scssの一番下に以下を記述

application.scss
@import "bootstrap-sprockets";
@import "bootstrap";

application.jsを編集する

application.jsの以下の部分を

application.js
//= require rails-ujs
//= require turbolinks
//= require_tree .

から

application.js
//= require rails-ujs
//= require jquery
//= require bootstrap-sprockets
//= require_tree .

に書き換えます。

index.html.erbを編集

index.html.erb
<div class="container">
  <h1>記事一覧</h1>
  <table class="table">
    <% @posts.each do |post| %>
      <tr>
        <td><%= post.title %></td>
        <td>
          <% if post.liked_by?(current_user) %>
            <% like = Like.find_by(user_id: current_user.id, post_id: post.id) %>
            <%= link_to like_path(like), method: :delete do %>
              <span class="glyphicon glyphicon-heart" aria-hidden="true" style="color: red;">
              <span><%= post.likes.count %></span>
            <% end %>
          <% else %>
            <%= link_to post_likes_path(post), method: :post do %>
              <span class="glyphicon glyphicon-heart" aria-hidden="true" style="color: gray;">
              <span><%= post.likes.count %></span>
            <% end %>
          <% end %>
        </td>
      </tr>
    <% end %>
  </table>
</div>

これで完成です。

参考記事