📑

いいね機能非同期通信化

2024/01/12に公開

はじめに

いいね機能非同期についてまとめます。
前提としていいね機能が実装されていることとします。

非同期通信の流れ

  1. ユーザーがいいねをクリックします。(ブラウザ上)
  2. ルーティングでどのコントローラのどのアクションを呼び出すか決める(routes.rb)
  3. アクションを実行する[いいねの保存や削除] (favorites.controller.rb)
  4. コントローラ名/アクション名.js.erbファイル内の処理を実行する[部分的にページを更新]
    (views/favorites/create.js.erb,views/favorites/destroy.js.erb)
  5. レスポンスを返す(ブラウザ上)

実装

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