Ruby on Rails5 X

いいね機能を作ろう

likesテーブルの役割
「どのユーザー」が「どの投稿」をいいねしたかを記録するために、データベースに「user_id」と「post_id」2つのカラムを持つlikesテーブルを用意しましょう。例えば下の図のように、user_idが1、post_idが2のデータは、「id:1のユーザーがid:2の投稿をいいねした」ということを表します。

likesテーブルを作成しよう
rails g modelrails db:migrate
右の図のコマンドを実行して、Likeモデルとマイグレーションファイルを用意しましょう。likesテーブルにはuser_idとpost_idの2つのデータを持たせるようにしてください。
マイグレーションファイルの用意ができたら「rails db:migrate」を実行して、データベースに反映させましょう。

バリデーションを追加する
validatespresence
いいねのデータは、user_idとpost_idの両方が常に存在していないと不完全なデータとなってしまいますので、最初にバリデーションを追加しておきましょう。user_idとpost_idのそれぞれに、値が存在していることをチェックする「presence: true」のバリデーションを追加します。

■ ターミナルで以下のコマンドを実行してください

rails g model Like user_id:integer post_id:integer

rails db:migrate

like.rb
class Like < ApplicationRecord validates :user_id, {presence: true} validates :post_id, {presence: true} end 「rails console」でデータを作成する newsaverails console コンソールでlikesテーブルにデータを追加してみましょう。「Like.new(user_id: 1, post_id: 2)」とすることで、「idが1のユーザーが、idが2の投稿にいいねした」というデータを作成することができます。 ■ ターミナルで以下のコマンドを実行してください rails console ■ コンソールで以下のコマンドを実行してください like = Like.new(user_id: 1, post_id: 2) like.save quit 「いいね!済み」と表示する条件 投稿詳細ページでは、「ログインしているユーザーがその投稿にいいねしたデータが存在する」という条件を満たす場合、「いいね!済み」と表示するようにしましょう。 逆に、この条件を満たしていない場合には「いいね!していません」と表示しましょう。 条件分岐 find_by 「ログインしているユーザーがその投稿にいいねしたデータが存在する」という条件のために、user_idとpost_idが合致するデータがlikesテーブルに存在するかどうか、find_byを用いてチェックします(find_byは該当するデータが見つからなかった時にnilを返すことを思い出しましょう)。 show.html.erb
<% if Like.find_by(user_id: @current_user.id, post_id: @post.id) %>
いいね!済み
<% else %>
いいね!していません
<% end %>

いいねボタンの準備
likesコントローラを用意しよう
今までコントローラは「rails g controller」コマンドで自動生成してきました。コマンドを用いるとビューファイルなども自動生成されますが、今回はそれらのビューファイルが必要ないので、コントローラを手動で作ってみましょう。controllersフォルダ内に「likes_controller.rb」というファイルを新規作成し、右の図のように大枠を記述するだけで作ることができます。

routes.rb
# createアクションに対応するルーティングを追加してください
post “likes/:post_id/create” => “likes#create”

likes_controller.rb
class LikesController < ApplicationController # before_actionに「:authenticate_user」を追加してください before_action :authenticate_user # createアクションを追加してください def create end end いいねボタンを作ろう createアクションを完成させよう newsave それではcreateアクションの中身を完成させましょう。 createアクション内では新たにデータを作成後、投稿詳細ページへとリダイレクトさせます。 user_idは@current_userから、post_idはparamsから取得して作成しましょう。 createアクションへのリンクを用意しよう link_to 作成したcreateアクションへのリンクを投稿詳細ページに追加しましょう。 下の図のように、今までは「いいね!していません」と表示していた部分を、「いいね!」するためのリンクに書き換えます。 likes_controller.rb def create # 変数@likeを定義してください @like = Like.new( user_id: @current_user.id, post_id: params[:post_id] ) # 変数@likeを保存してください @like.save # 投稿詳細ページにリダイレクトしてください redirect_to("/posts/#{params[:post_id]}") end show.html.erb
<%= link_to("いいね!", "/likes/#{@post.id}/create", {method: "post"}) %>

いいね取り消しボタンを作ろう
destroyアクションを用意しよう
find_bydestroy
「いいね!」を取り消す機能を作るために、まずはlikesコントローラにdestroyアクションを作成しましょう。destroyアクション内では、受け取った@current_user.idとparams[:post_id]をもとに削除すべきLikeデータを取得し、destroyメソッドを用いて削除します。

routes.rb
# destroyアクションに対応するルーティングを追加してください
post “likes/:post_id/destroy” => “likes#destroy”

show.html.erb
<% if Like.find_by(user_id: @current_user.id, post_id: @post.id) %>

<%= link_to("いいね!済み", "/likes/#{@post.id}/destroy", {method: "post"}) %>
<% else %>

likes_controller.rb
# destroyアクションを定義してください
def destroy
@like = Like.find_by(user_id: @current_user.id, post_id: params[:post_id])
@like.destroy
redirect_to(“/posts/#{params[:post_id]}”)
end

いいねボタンをアイコンにしよう(1)
Font Awesomeとは
「Font Awesome」とは、様々なアイコンをフォントとして利用できるようにしたものです。
HTML & CSS 学習コース 中級編でも用いたので、忘れてしまった場合は復習をしておきましょう。

Font Awesomeの読み込み
「Font Awesome」を利用するには、タグ内で読み込みをする必要があります。
タグなどの共通のHTMLはapplication.html.erbに書きますので、
今回はそこに読み込み用のタグを追加しましょう。

ハートアイコンの表示
左の図のようにに「fa fa-heart」というクラス名をつけることで、ハートアイコンを表示することができます。しかし、右の図のようにlink_toメソッド内にHTML要素を記述すると正しく表示することができません。
HTML要素に対してlink_toメソッドを使う方法を次のスライドで見てみましょう。

HTML要素に対して
link_toメソッドを使う
link_todo
HTML要素に対してlink_toメソッドを使うには、少し異なる書き方をする必要があります。
右の図のように、<%= link_to(URL) do %>と<% end %>の間にHTML要素を書くことで、その部分をリンクにすることができます。

ink_toメソッドで
ハートアイコンを表示する
link_todo
link_toメソッドでハートアイコンを表示してみましょう。
下の図のように、<%= link_to("URL") do %>と<% end %>の間にを書き、「fa fa-heart 」というクラス名をつけることでハートアイコンのリンクを作ることができます

show.html.erb
<% if Like.find_by(user_id: @current_user.id, post_id: @post.id) %>

<%= link_to("/likes/#{@post.id}/destroy", {method: "post"}) do %>

<% end %>
<% else %>

<%= link_to("/likes/#{@post.id}/create", {method: "post"}) do %>

<% end %>

posts.scss
// .like-btnのcolorを「#8899a6」にしてください
.like-btn {
color: #8899a6;
}

// .like-btn-unlikeのcolorを「#ff2581」にしてください
.like-btn-unlike {
color: #ff2581;
}

// ここに指定されたCSSを貼り付けてください
.posts-show-item .fa {
font-size: 16px;
margin-right: 3px;
}

countメソッド
count
likesテーブルからデータの件数を取得するには、countメソッドを用います。countメソッドは配列の要素数を取得するメソッドですが、テーブルのデータ数を取得するためにも利用することができます。

show.html.erb

<%= @likes_count %>

posts_controller.rb
def show
@post = Post.find_by(id: params[:id])
@user = @post.user
# 変数@likes_countを定義してください
@likes_count = Like.where(post_id: @post.id).count
end

いいねした投稿を表示しよう(1)
likesアクションを用意する
「いいね!」をした投稿を一覧で表示するために、likesアクションをusersコントローラ内に作成しましょう。
ルーティングのURL部分はshowアクションと同様に、どのユーザーに関する情報を表示するかを判断するために「users/:id/likes」とします。

# “users/:id/likes”に対応するルーティングを追加してください
get “users/:id/likes” => “users#likes”

users_controller.rb
# likesアクションを追加してください
def likes
end

show.html.erb

  • <%= link_to("投稿", "/users/#{@user.id}") %>
  • <%= link_to("いいね!", "/users/#{@user.id}/likes") %>

likesアクションを完成させよう
where
ビューで用いる変数をアクション内で定義しましょう。
whereメソッドを用いてそのユーザーに関するデータをlikesテーブルから取得し、変数@likesに代入します。

likesアクションのビュー
find_by
likesアクション内で定義した変数@userと@likesを用いて、ビューも完成させましょう。
各投稿を1つずつ表示するためには、@likesに対してeach文を用いて、likeに紐付いているpostを表示させます。

users_controller.rb
def likes
# 変数@userを定義してください
@user = User.find_by(id: params[:id])

# 変数@likesを定義してください
@likes = Like.where(user_id: @user.id)
end

likes.html.erb

<% @likes.each do |like| %>

<% post = Post.find_by(id: like.post_id) %>

“>
<%= link_to(post.user.name, "/users/#{post.user.id}") %>

<%= link_to(post.content, "/posts/#{post.id}") %>


<% end %>

シェアする

  • このエントリーをはてなブックマークに追加

フォローする