【Rails】いいね機能の実装手順

Ruby on Rails

Railsアプリケーションにいいね機能を実装する手順をまとめました。

マイグレーションファイルでlikesテーブルを作成

カラムはuser_id(いいねしたユーザーid)とpost_id(いいねされた投稿id)を使用します。

$ rails generate model Like user_id:integer post_id:integer

インデックスを追加

user_idとpost_idの組み合わせでインデックス作成とunique: trueで一意制約を設定します。

app/db/migrate/YYYYMMDDHHMMSS_create_likes.rb


class CreateLikes < ActiveRecord::Migration[5.1]
  def change
    create_table :likes do |t|
      t.integer :user_id
      t.integer :post_id

      t.timestamps

      add_index :likes, :user_id
      add_index :likes, :post_id
      add_index :likes, [:user_id, :post_id], unique: true
    end
  end
end

データベースに反映

$ rails db:migrate

$ rails genarate model Like ...からインデックス追加せずに$ rails db:migrateを実行してしまった場合、ロールバックするか、別のマイグレーションファイルを作成して$ rails genarate ...でインデックスだけ追加する必要があります。

バリデーションを追加

likeモデル

user_idとpost_idは必須で、user_id_はpost_idとの組み合わせで一意となるように設定します。
userとpostテーブルに関連付けします。

app/models/like.rb

class Like < ApplicationRecord
  validates :user_id, presence: true, uniqueness: {scope: :post_id}
  validates :post_id, presence: true
  belongs_to :post
  belongs_to :user
end

userモデル

1対多の関連付けと、投稿削除時にlikesも消えるように設定します。

app/models/user.rb


class User < ApplicationRecord
.
.
  has_many :likes, dependent: :destroy
.
.
end

postモデル

userモデルと同様に1対多の関連付けと稿削除時にlikesも消えるように設定します。

app/models/post.rb

class Post < ApplicationRecord
.
.
  has_many :likes, dependent: :destroy
.
.
end

ルーティング追加

posts/1/likes のようなURLにするためネストで記述しました。
ネストについてのRailsガイド

config/routes.rb

Rails.application.routes.draw do
.
.
  resources :posts, only: [:create, :destroy, :show] do
    resources :likes, only: [:create, :destroy]
  end
.
.
end

Likesコントローラ作成

今回は手動でファイルを作成します。

$ touch app/controllers/likes_controller.rb

crate/destroyアクションを追記します。

app/controllers/likes_controller.rb


class LikesController < ApplicationController

  def create
    @like = current_user.likes.new(post_id: params[:post_id])
    if @like.save
      flash[:success] = "いいね登録しました"
      redirect_to "/posts/#{params[:post_id]}"
    end
  end

  def destroy
    @like = Like.find_by(user_id: current_user.id, post_id: params[:post_id])
    if @like.destroy
      flash[:success] = "いいね解除しました"
      redirect_to "/posts/#{params[:post_id]}"
    end
  end

end

flashの表示やredirect_toのリダイレクト先はお好みで設定してください。

current_userヘルパーを app/helpers/sessions_helper.rb に定義しています。

module SessionsHelper
.
.
  def current_user
    if session[:user_id]
      @current_user = @current_user || User.find_by(id: session[:user_id])
    end
  end
.
.
end

ビューにリンクを作成

現在のユーザーでこの投稿に対するいいねがある場合は「いいね解除」を表示し、ない場合は「いいね」を表示するようにします。

app/views/posts/show.html.erb 等


.
.

<% if current_user.likes.find_by(post_id: @post.id) %>
  <%= link_to "いいね解除", post_like_path(@post), method: :delete %>
<% else %>
  <%= link_to "いいね", post_likes_path(@post), method: :post %>
<% end %>
.
.

ここではいいねボタンは普通のリンクとしています。

コメントを残す

メールアドレスが公開されることはありません。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください