#目次
1.はじめに
2.いいねボタンの導入
3.同期通信で実装する
4.非同期通信で実装する
5.おわりに
#1. はじめに
今回は同期通信で実装した後、それをもとに非同期通信に切り替えていきます。まずは必要なものを導入しましょう。
#2. いいねボタンの導入
font-awesome-rails
を導入しましょう。もし文字をクリックしてお気に入り機能を実装する場合であれば3.同期通信で実装するから実装していただいて問題ないです。以下のようにアイコンをクリックしてお気に入りをつけたり外したりしたい場合はこちらを参考にしてください。
###1. GEMの導入
gem 'font-awesome-rails'
*導入したら必ずbundle install
してください。
###2. CSSファイルに記述を追加する
*= require font-awesome
これで使う準備はOKです。
###3. 使用したいビューファイルに記述を追加する
<i class="fa fa-アイコン名" aria-hidden="true"></i>
どんなアイコンを使用するかはご自由に!!
[ここをクリック!][link-1]から探してね!!
[link-1]:https://fontawesome.com/v4.7.0/icons/
#3. 同期通信で実装する
アプリケーション作成、ユーザー登録、投稿機能ができている体で進みます。そこまでは自力で実装してください。
###1. お気に入り機能に必要なものを揃える
まずは必要なもの...そうですコントローラーとモデルですね!
どんな名前でもいいので作成してください。今回この記事ではlike
という名前で実装してます。
###2. ルーティングの設定
今回は投稿機能に関連する機能のため、ネスト構造で設定します。今回はお気に入りをつけて外すだけなのでcreate
とdestroy
のみ記述してます。
Rails.application.routes.draw do
#(省略)
resources :posts do
resources :likes, only: [:create, :destroy]
end
end
###3. モデルの設定
まず、マイグレーションファイルにはuser_id
とpost_id
が保存できるように設定してマイグレートしておいてください。
今回1人のユーザーはお気に入りを何回もすることができます。また、投稿された物に対してもたくさんお気に入りすることができます。
そのため以下のようにアソシエーションを設定します。
class Like < ApplicationRecord
belongs_to :user
belongs_to :post
end
#以下を追加する
has_many :likes
#以下を追加する
has_many :likes
###4. コントローラーの設定
まずはお気に入りを登録するcreateアクション
の設定です。
今回は投稿したpostに対して行いたいためまずはどのpostなのかを取得する必要があります。その後、そのpostに対してお気に入りを新しく作り、保存ができたらトップページに戻るように設定します。
お気に入りの削除は今の考え方で、保存ではなく削除したら...の場合で記述しましょう。
以下のようになります。
class LikesController < ApplicationController
before_action :set_post
def create
@like = Like.new(user_id: current_user.id, post_id: params[:post_id])
@like.save
redirect_to root_path
end
def destroy
@like = current_user.likes.find_by(post_id: @post.id)
@like.destroy
redirect_to root_path
end
private
def set_post
@post = Post.find(params[:post_id])
end
end
###5. ビューファイルの設定
お気に入り機能だけを別に切り出したいので今回私は部分テンプレートに記述しました。そのため、元々の記述の部分は以下のようになります。
#(省略)
<div class="likes_heart" id="post_<%= post.id %>">
<%= render "likes/like", post: post %>
</div>
部分テンプレートでは、以下の条件をつけました。
・ログインしていないとお気に入りできない
・1投稿に対して1回しかお気に入りができない(既にお気に入りに登録していたら削除するボタンになる)
<% if user_signed_in? %>
<% if post.liked_by?(current_user) %>
<%=link_to post_like_path(post_id: post.id, id: post.id), method: :delete do%>
<i class="fa fa-heart" aria-hidden="true" id="heart"></i>
<%= post.likes.count %>
<% end %>
<% else %>
<%=link_to post_likes_path(post), method: :post do%>
<i class="fa fa-heart" aria-hidden="true" id="heart"></i>
<%= post.likes.count %>
<% end %>
<% end%>
<% end %>
また、今回liked_byというメソッドを使用します。whereメソッドを使用し、likesテーブルに「user_id」が存在しているかどうか検索をかけています。(存在すれば削除、存在しなければお気に入り追加、と振り分ける)
#省略
def liked_by?(user)
likes.where(user_id: user.id).exists?
end
同期通信はこれで終わり!!!実際に動かしてみてください!!
#4. 非同期通信で実装する
ここが本当に難しい...と感じました!もう少し!頑張りましょう!!
###1. コントローラーの修正
非同期通信に変更するのでトップページに遷移させる記述を削除しましょう。
以下のようになります。
class LikesController < ApplicationController
before_action :set_post
def create
@like = Like.new(user_id: current_user.id, post_id: params[:post_id])
@like.save
end
def destroy
@like = current_user.likes.find_by(post_id: @post.id)
@like.destroy
end
private
def set_post
@post = Post.find(params[:post_id])
end
end
###2. ビューファイルの設定
「remote: true」を付与します。付与することで、パラメーターがHTML形式ではなくJS形式で送られるようになります。
今回の場合は「remote: true」をlink_toメソッドに付与することで、likes_controller.rbのcreateアクション後は、views/likes/create.js.erbが呼び出されるようになります。
<% if user_signed_in? %>
<% if post.liked_by?(current_user) %>
<%=link_to post_like_path(post_id: post.id, id: post.id), method: :delete,remote: true do%>
<i class="fa fa-heart" aria-hidden="true"></i>
<%= post.likes.count %>
<% end %>
<% else %>
<%#link_to post_likes_path(post), method: :post do%>
<%= link_to post_likes_path(post), method: :post, remote: true do%>
<i class="fa fa-heart" aria-hidden="true"></i>
<%= post.likes.count %>
<% end %>
<% end%>
<% end %>
###3. js.erbファイルの作成
今回は2つ用意しましょう。
記述は以下です。
document.getElementById('post_<%= @post.id %>').innerHTML = '<%= j(render 'like' ,post: @post) %>'
document.getElementById('post_<%= @post.id %>').innerHTML = '<%= j(render 'like' ,post: @post) %>'
詳しくみていきましょう。
まずはこちらです。
document.getElementById('post_<%= @post.id %>')
書き換えたいビューのIDを取得しています。
IDに関しては、3.同期通信で実装するの5.ビューファイルの設定で設定してますので確認してください。
'<%= j(render 'like' ,post: @post) %>'
部分テンプレートの内容に置き換えることを表してます。
今回使用した部分テンプレートは_like.html.erb
なのでこのような書き方です。部分テンプレートに保存/削除した内容を渡さないといけないので、部分テンプレート内で使用している変数post: @post
を記述してます。
#5. おわりに
普通にJSファイルを作成して行うやり方もあると思います。皆さんがしっくりくるやり方で実装してみてください!!