Rails いいね機能の非同期通信化
「Ajax」とは
JavaScript(Ajaxを構成する中核)を使って、非同期にサーバー間での通信を行うこと。
例えば、ページを再読み込みしたり、「送信」ボタンは押していないのに、TwitterやFacebookで「いいね」ボタンを押すと、すぐに「いいね」アイコンに変わること。
Ajaxを使うことで、Webページ全体を更新することなく「一部分だけ情報を更新する」ことが可能になる。
非同期の処理の流れ
-
ユーザーがいいねをクリックする
(Webブラウザ) -
ルーティングでどのコントローラのどのアクションを呼び出すか決める
-
アクションを実行する(いいねの保存や削除)
-
コントローラ名・アクション名・js.erbファイル内の処理を実行する
(部分的にページを更新) -
レスポンスを返す
(Webブラウザ)
jQueryの読み込み
gem 'jquery-rails'
bundle install を忘れずに行う。
部分テンプレート作成&いいねボタンにAjaxの処理を適用
部分テンプレートで作成しました。
<% if book.favorited_by?(current_user) %>
<p>
<%= link_to book_favorites_path(book), method: :delete, remote: true, data: {"turbolinks" => false} do %>
<i class="fas fa-heart" aria-hidden="true" style="color: red;"></i>
<span style="color: red;"><%= book.favorites.count %></span>
<% end %>
</p>
<% else %>
<p>
<%= link_to book_favorites_path(book), method: :post, remote: true, data: {"turbolinks" => false} do %>
♡<%= book.favorites.count %>
<% end %>
</p>
<% end %>
link_to内にremote; true を追加することで、
HTMLリクエストではなく、JavaScriptのリクエストがfavoritesコントローラに送られる!!
HTMLリクエストの場合
→データベースにいいねを保存or削除し、画面にリダイレクト(ページを読み込む)
JavaScriptリクエストの場合
→データベースにいいねを保存or削除し、JavaScriptを使っていいね部分のみ更新(ページ読み込みなし)
data: {"turbolinks" => false}
turbolinksを限定的に動かないようにするために記入。この記入がないと、リロードしないと反映されなくなる。
:
省略
:
<tbody>
<% books.each do |book| %>
<tr>
<td><%= link_to book.user do %>
<%= image_tag book.user.get_profile_image(50, 50) %>
<% end %>
</td>
<td><%= link_to book.title,book, class: "book_#{book.id}" %></td>
<td><%= book.body %></td>
<!--いいね機能ajax-partial-->
<td id="favorite_buttons_<%= book.id %>" >
<%= render "favorites/favorite", book: book %>
</td>
<td><p>コメント件数:<%= book.post_comments.count %></p></td>
<td><%= render "books/static_rate", book: book %></td>
</tr>
:
<% end%>
この箇所の更新を指定するために、変更したい箇所にidで名前をつけている。
いいね保存、削除のリダイレクト先を削除
class FavoritesController < ApplicationController
def create
@book = Book.find(params[:book_id])
favorite = @book.favorites.new(user_id: current_user.id)
favorite.save
#redirect_back(fallback_location: root_path)
end
def destroy
@book = Book.find(params[:book_id])
favorite = current_user.favorites.find_by(book_id: @book.id)
favorite.destroy
#redirect_back(fallback_location: root_path)
end
end
リダイレクト先を削除したことにより、
リダイレクト先がない&JavaScriptリクエストという状況になり、
createアクション実行後は、create.js.erbファイルを、
destroyアクション実行後はdestroy.js.erbファイルを探してくれる。
部分テンプレートを読み込む
<td id="favorite_buttons_<%= @book.id %>" >
<%= render "favorites/favorite", book: @book %>
</td>
この箇所の更新を指定するために、変更したい箇所にidで名前をつける。
id="favorite_buttons_<%= book.id %>"
js.erbファイルの編集
$('#favorite_buttons_<%= @book.id %>').html("<%= j(render "favorites/favorite", book: @book) %>");
$('#favorite_buttons_<%= @book.id %>').html("<%= j(render "favorites/favorite", book: @book) %>");
急いで書いたので抜けているところがあるかもしれないです><
今日はここまで。
参考にさせていただいた記事
Discussion