いいね機能の仕組み
「どのユーザーがどの投稿にいいねしたか」をデータとして管理するのがいいね機能。
まずはデータを保存するために、データベースにlikesテーブルを作成する
likeテーブルの役割
「どのユーザー」が「どの投稿」をいいねしたかを記録するために、データベースに「user_id」と「post_id」2つのカラムを持つlikesテーブルを用意する。
【例】
user_idが1、post_idが2のデータは、「id:1のユーザーがid:2の投稿をいいねした」ということを表す
likeテーブルを作成する
コマンドを実行して、Likeモデルとマイグレーションファイルを用意する。
STEP.1 マイグレーションファイルを作成する
《ターミナル》
$ rails g model Like user_id:integer post_id:integer テーブル名 カラム名 データ名
- integerは整数を扱うデータ型
STEP.2 データベースに変更を反映する
《ターミナル》
$ rails db:migrate
STEP.3 バリデーションを追加する
いいねのデータは、user_idとpost_idの両方が常に存在していないと不完全なデータとなってしまうため、最初にバリデーションを追加しておく。
《models/like.rb》
class Like< Application
validates :user_id,{presence: true}
validates :post_id,{presence: true}
end
- user_idとpost_idのそれぞれに、値が存在していることをチェックする「presence: true」のバリデーションを追加
いいねのデータを作成してみる
コンソールでlikesテーブルにデータを追加してみる
《ターミナル》
$ rails console
like = Like.new(user_id: 1, post_id: 2)
↑ユーザーidが1の人が、idが2の投稿にいいねしたデータを作成
like.save
いいねした投稿かどうか表示する
投稿詳細ページでは、「ログインしているユーザーがその投稿にいいねしたデータが存在する」という条件を満たす場合、「いいね!済み」と表示。
逆に、この条件を満たしていない場合には「いいね!していません」と表示。
《posts/show.html.rb》 条件分岐を作成する
<% if Like.find_by(user_id: @current_user.id, post_id: @post.id)%>
いいね!済み
<% else %>
いいね!していません
<% end %>
- likeテーブルの中にログイン中のユーザーが かつ いいねした投稿データ を満たすデータがあるかどうかをfind_byを用いて確認
- →likeテーブルの中で、ログイン中のユーザーが投稿にいいねしたデータが存在するかどうか確認する
- 【復習】find_byは該当するデータが見つからなかった時にnilを返す
いいね!ボタン
実際にいいねしたり、取り消したりできるようにする。
likesコントローラを作成して、likeデータを作成するためのアクションを用意する。
likeコントローラを用意する
今までコントローラは「rails g controller」コマンドで自動生成してきたけど、コマンドを用いるとビューファイルなども自動生成されてしまう。
今回はそれらのビューファイルが必要ないので、コントローラを手動で作る。
tweet_app/→app/→controllers/→likes_controller.rb 新規ファイル作成で作る
createアクションを用意する
作成したlikesコントローラに、新たにLikeデータを作成するためのcreateアクションを用意する。
《likes_controller.rb》
class LikesController < ApplicationController
before_action :authenticate_user
def create
end
end
《ルーティング》
post “likes/:post_id/create” => “likes#create”
- createはデータベースにデータを作成するアクションなので、ルーティングには「post」を使う
- URLの部分は「どの投稿をいいねしたのか」という情報を送信するために、「likes/:post_id/create」とする →「likes/1/create」や「likes/2/create」に対応する
いいねボタンを完成させる
createアクションの中身を書いて、そのアクションへのリンクを「いいねボタン」として、投稿詳細ページに追加する
《likes_controller.rb》
class LikesController < ApplicationController
before_action :authenticate_user
def create
@like = Like.new(
user_id: @current_user.id ← user_idはログイン中のユーザーidから
post_id: params[:post_id] ← post_idはparams[:post_id]から値を取得して
) 新たにデータを作成する
@like.save ←そのデータを保存する
redirect_to(“/posts/#{params[:post_id]}“) ←作成後は、投稿詳細ページへリダイレクトする
end
end
《ルーティング》
post “likes/:post_id/create” => “likes#create”
作成したcreateアクションへのリンクを用意する
作成したcreateアクションへのリンクを投稿詳細ページに追加する
《posts/show.rb》
<% if Like.find_by(user_id: @current_user.id, post_id: @post.id)%>
いいね!済み
<% else %>
いいね!していません
↓これに書き換え
<%= link_to(“いいね!”,”/likes/#{:post.id}/create”,{method: “post”})%>
<% end %>
- 今までは「いいね!していません」と表示していた部分を、「いいね!」するためのリンクに書き換える
- createアクションのルーティングはpostですので、link_toメソッドの引数に{method: “post”}を書き忘れないように注意
いいね!取り消しボタンを作る
「いいね!」を取り消す機能を作るために、まずはlikesコントローラにdestroyアクションを作成する
《likes_controller.rb》
def destroy
@like = Like.find_by( ←削除すべきLikeデータを取得
user_id: @current_user.id ← 削除すべきデータは
post_id: params[:post_id] 受け取った@current_user.idとparams[:post_id]
)
@like.destroy ←destroyメソッドを用いて削除
redirect_to(“/posts/#{params[:post_id]}”)
end
《ルーティング》
post “likes/:post_id/destroy” => “likes#destroy”
destroyアクションへのリンクを用意する
《posts/show.rb》
<% if Like.find_by(user_id: @current_user.id, post_id: @post.id)%>
いいね!済み
↓書き換える
<%= link_to(“いいね!済み”,”/likes/#{:post.id}/destroy”,{method: “post”})%>
<% else %>
<%= link_to(“いいね!”,”/likes/#{:post.id}/create”,{method: “post”})%>
<% end %>
- 今までは「いいね!済み」と表示していた部分を、「いいね!」を取り消すためのリンクに書き換える
いいね!ボタンをアイコンにする
「Font Awesome」を使って、いいねボタンをハートのアイコンにする
Font Awesomeの読み込み
「Font Awesome」を利用するには、<head>タグ内で読み込みをする必要がある。
共通部分を書くapplication.html.erbに、読み込み用の<link>タグを追加する
《application.html.erb》
<head>
<link rel=”stylesheet” href=”https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css”> ←Font Awesomeの読み込み
</head>
ハートアイコンの表示
<span>に「fa fa-heart」というクラス名をつけることで、ハートアイコンを表示することができるが
link_toメソッドの中ではうまく表示できない。
HTML要素に対してlink_toメソッドを使うには、<%= link_to(URL) do %>と<% end %>の間にHTML要素を書くことで、その部分をリンクにできる。
《posts/show.rb》
<%= link_to(“URL”) do %>
ここにコードを記載する
<% end %>
|
| 実際にやってみる
↓
<%= link_to(“/likes/#{@post.id}/create”,{method: “post”})%>
<span class=”fa-fa heart unliked-btn”></span> リンクになるHTML要素
<% end %>
いいね数を取得する
likesテーブルからデータの件数を取得するには、countメソッドを使う。
countメソッドは配列の要素数を取得するメソッドですが、テーブルのデータ数を取得するためにも利用できる。
《ターミナル》
$ rails console
Like.all.count ← Likesテーブルの全データの数を取得
→ 3
Like.where(post_id: 1).count ←likeテーブルの、post_idが1の数
→ 2
《posts.controller》
def show
@post = Post.find_by(id: params[:id])
@user = @post.user
@likes_count = Like.where(post_id: @post.id).count
end
《posts/show.html》
<%= @likes_count %> ←これでカウント数を表示
- ここは、すでにfind_byで取得した投稿のidなので、params[:id]ではなく、@post.id!
いいね!した投稿の一覧を表示する
あるユーザーが「いいね!」した投稿一覧を表示するようにする。
今回はユーザーに関するページを作成するので、likesコントローラではなく、usersコントローラにlikesアクションを作成する
likesアクションを用意する
《ルーティング》
get “users/:id/likes” => “users#likes”
URL部分はshowアクションと同様に、どのユーザーに関する情報を表示するかを判断するために「users/:id/likes」とする。
《users_controller.rb》
def likes
end
《ビュー:user_likes.html.erb》
《users/show.html.erb》
<ul class=”user-tabs”>
<li class=”active”><%= link_to(“投稿”, “/users/#{@user.id}”) %></li>
<li><%= link_to(“いいね!”, “/users/#{@user.id}/likes”) %></li>
</ul>
likesアクションを完成させる
《users_controller.rb》
def likes
@user = User.find_by(id: params[:id]) ← params[:id]を用いてユーザー情報を取得
@likes = Like.where(user_id: @user.id)
end
- whereメソッドを用いてそのユーザーに関するデータをlikesテーブルから取得し、変数@likesに代入
likeアクションのビュー
ikesアクション内で定義した変数@userと@likesを用いて、ビューも完成させる。
あるユーザーが「いいね!」した投稿を1つ1つ表示するようにする
《user_likes.html.erb》
<%= @likes.each do |like| %>
<% post = Post.find_by(id: like.post_id)%> 変数likeに紐づく投稿を表示
<% end %>
- 各投稿を1つずつ表示するためには、@likesに対してeach文を用いて、likeに紐付いているpostを表示させる
コメント