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 %>
.
.
ここではいいねボタンは普通のリンクとしています。
Tweet