📑
いいね機能非同期通信化
はじめに
いいね機能非同期についてまとめます。
前提としていいね機能が実装されていることとします。
非同期通信の流れ
- ユーザーがいいねをクリックします。(ブラウザ上)
- ルーティングでどのコントローラのどのアクションを呼び出すか決める(routes.rb)
- アクションを実行する[いいねの保存や削除] (favorites.controller.rb)
- コントローラ名/アクション名.js.erbファイル内の処理を実行する[部分的にページを更新]
(views/favorites/create.js.erb,views/favorites/destroy.js.erb) - レスポンスを返す(ブラウザ上)
実装
Gemfile
gem 'jquery-rails'
bundle install
を忘れずに
_btn.html.erb
<% 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を限定的に動かないようにするために記入。この記入がないと、リロードしないと反映されなくなる。
いいね機能のリダイレクト先を消す
これをすることによりブラウザ上に介すことなくいいねができたり消したりできます。
favorites.controller.erb
class FavoritesController < ApplicationController
before_action :authenticate_user!
def create
@book = Book.find(params[:book_id])
favorite = current_user.favorites.new(book_id: @book.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
リダイレクト先を削除したことにより、
リダイレクト先がない、かつJavaScriptリクエストという状況になり、
createアクション実行後は、create.js.erb
ファイルを、
destroyアクション実行後はdestroy.js.erb
ファイルを探すようになります。
jsファイル編集
create.js
$('#favorite_buttons_<%= @book.id %>').html("<%= j(render "favorites/favorite", book: @book) %>");
destroy.js
$('#favorite_buttons_<%= @book.id %>').html("<%= j(render "favorites/favorite", book: @book) %>");
終わりに
急いで書き殴ったため何か間違い、質問等ありましたらコメントお願いします。
Discussion