##はじめに
今回は前提としてUser, Postが既にあり、Likeを加えた3つのモデルでできるアプリとします。
1.Likesモデルの追加
2.アソシエーション
3.Likesコントローラの追加
4.Likesコントローラの設定
5.Postsコントローラの設定
6._like.html.erbの追加
##Likesモデルの追加
$ rails g model like post:references user:references
$ rails db:migrate
##アソシエーション
class Like < ApplicationRecord
belongs_to :user
belongs_to :post
end
post.rbの最後の行はlikesテーブルを中間テーブルとして経由してuserテーブルから情報を取ってくると言うことを表してます。
liked_usersにしていますが、ここはわかりやすい名前にして下さい。
class Post < ApplicationRecord
belongs_to :user
has_many :likes
has_many :liked_users, through: :likes, source: :user
end
post.rbと同様でlikesを経由してpostテーブルから情報を取ってきてliked_postsと言う名前で使用できます。
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :posts, dependent: :destroy
has_many :likes, dependent: :destroy
has_many :liked_posts, through: :likes, source: :post
#ユーザーが投稿に対して既にいいねしているか
def already_liked?(post)
likes.exists?(post_id: post.id)
end
end
##Likesコントローラの追加
$ rails g controller likes
##Likesコントローラの設定
-
create:
ログインユーザーがあるpostに対してlikeする -
destroy:
ログインユーザーがlikeしたpostを探して削除 -
set_post:
JSでなんとか出来るけどとりあえずいいねしたらredirectでpost#showへ遷移。
しかし、今のままではlikes_controllerで@postは使えないのでprivate下で@postを定義する。
class LikesController < ApplicationController
before_action :set_post, only: [:create, :destroy]
def create
@like = current_user.likes.create(post_id: params[:post_id])
redirect_to post_path(@post)
end
def destroy
@like = Like.find_by(post_id: params[:post_id], user_id: current_user.id)
@like.destroy
redirect_to post_path(@post)
end
private
def set_post
@post = Post.find(params[:post_id])
end
end
##Postsコントローラの設定
今回はPosts#showでいいね出来るようにするのでshowアクションに以下を付け加える。
def show
@post = Post.find(params[:id])
@comments = @post.comments.includes(:user)
--------↓これを加えてください-------
@like = Like.new
end
##_like.html.erbの追加
**1行目:**user.rbで作った、記事に対していいねしているかどうかのメソッドです。
ログイン中のユーザーがあるpostにいいねしているのなら2~4行目の処理に行きます。
まだいいねしていないのなら6~8行目の処理に行きます。
**2~4行目:**いいね削除メソッドで、fontawesomeの❤️アイコンとdeleteメソッドをブロックを使って一体化しています。
またremote: trueを記述することで非同期でいいねすることができます。
**6~8行目:**いいねメソッドです。それ以外は2~4行目と同じです。
**10行目:**ある記事に対していいねされた数をカウントします。
<% if current_user.already_liked?(@post) %>
<%= link_to post_like_path(@post), method: :delete, remote: true do %>
<%= fa_icon 'heart', id: "heart__red" %>
<% end %>
<% else %>
<%= link_to post_likes_path(@post), method: :post, remote: true do %>
<%= fa_icon 'heart', id: "heart__normal" %>
<% end %>
<% end %>
<%= @post.liked_users.count %>
##最後は
部分テンプレートを使って_like.html.erbを呼び出します。
<div class="post__like">
<%= render 'likes/like' %>
</div>
##参考