🐣

[Ruby on Rails] いいね機能の非同期通信

2023/07/08に公開

非同期通信とは

  • ネットワークなどで繋がれているコンピューター間で、送信者のデータ送信タイミングと受信者のデータ受信タイミングを合わせずに通信を行う通信方法です。
  • 同期通信はデータ通信のリクエストを出してからレスポンスが来るまで他の処理を行わないが、非同期通信ではレスポンスが来るまでに他の処理を行える。

Ajax とは?

  • Ajaxとは、JavaScript でサーバー側との通信を「非同期」で行い、通信結果によって 「動的にページの一部だけ書き換える手法のこと」 です。

今回のいいね機能の非同期通信では、いいねボタンを押したら、リロードされずにいいねアイコンが変わるようにしたいので、 Ajax を使用します

gem の追加

Gemfile
gem 'jquery-rails'

gem を追加したら、インストールします

$ bundle install

いいねの view ページに Ajax の処理を追加

今回は 部分テンプレートにいいねの view ページを作成しています

favorites/_btn.html.erb
<% if book.favorited_by?(current_user) %>
  <%= link_to book_favorites_path(book), method: :delete, remote: true do %><%= book.favorites.count %>
  <% end %>
<% else %>
  <%= link_to book_favorites_path(book), method: :post, remote: true do %><%= book.favorites.count %>
  <% end %>
<% end %>
解説
  • remote: true と書くことで、 Ajax 通信でリクエストを送信できる様になります
    • Ajax 通信 簡単に言うと 部分的に通信ができる通信方法
      今回は使用していませんが、普段はこちら
  • local: true こちらは HTML 通信でリクエストが送信されるようになります
    • HTML 通信 簡単に言うと ページ全体をリロードして、通信する通信方法

index の View ページも変更

こちらも部分テンプレートに書いてあります

books/_index.html.erb
<table>
  <% books.each do |book| %>
  <td id="favorite_buttons_<%= book.id %>">
    <%= render "favorites/btn", book: book %>
  </td>
</table>
  • id を使用して、更新したいところに名前をつけます

コントローラーの変更

favorites.controller
  def create
    @book = Book.find(params[:book_id])
    favorite = current_user.favorites.new(book_id: @book.id)
    favorite.save
    # redirect_to request.referer 
  end

  def destroy
    @book = Book.find(params[:book_id])
    favorite = current_user.favorites.find_by(book_id: @book.id)
    favorite.destroy
    # redirect_to request.referer 
  end
  • この2箇所をコメントアウト、または削除します
  • リダイレクト先を削除することで、 Ajax 通信と HTML 通信を混同させない様にします
  • 結果 create アクション実行後は create.js.erb ファイルを
    destroy アクション実行後は destroy.js.erb ファイルが実行されます

js.erb ファイル

まずは 以下のファイルを作成します

  • favorites/create.js.erb
  • favorites/destroy.js.erb

次に中身を記述します

favorites/create.js.erb
$('#favorite_buttons_<%= @book.id %>').html("<%= j(render "favorites/btn", book: @book) %>");
favorites/destroy.js.erb
$('#favorite_buttons_<%= @book.id %>').html("<%= j(render "favorites/btn", book: @book) %>");
プチ解説
  • (render で呼び出す際に書いた id 名).html( 部分テンプレートの呼び出し)の形になっている
  • j は escape_javascript の略
  • javascript の中で HTML を記述する際に実行結果を エスケープするためのメソッド

こちらの記事を参考にさせていただきました

Discussion