💻

いいね機能(非同期通信)

2023/10/03に公開

Ajaxとは

「Asynchronous JavaScript + XML」の略(Asynchronous:非同期)。
HTMLリクエストでは画面全体の遷移によって更新を行っていますが、Javascriptリクエストを行うことでページの一部分だけを更新することが可能になります。今回はこのAjaxのしくみを使って具体的にどのように実装を進めて行くかを記述します。Javascriptと聞いて少しおよび腰になってしまいますが、私はJavascriptの知見はありませんでしたが実装できましたのでご安心下さい。

jQueryのインストール

Gemfile.
gem 'jquery-rails'

JavascriptのライブラリであるjQueryをインストールします。
ターミナルでbundle installを忘れず行いましょう。

いいねボタンにAjaxを適応させる

favorites/_btn.html.erb
<% if book.favorited_by?(current_user) %>
  <%= link_to book_favorites_path(book), method: :delete, remote: true, style: "color: red;" do %>
    <i class="fas fa-heart" aria-hidden="true"></i>
    <%= book.favorites.count %>
  <% end %>
<% else %>
  <%= link_to book_favorites_path(book), method: :post, remote: true do %>
    <i class="fas fa-heart" aria-hidden="true"></i>
    <%= book.favorites.count %>
  <% end %>
<% end %>

今回は、いいね機能を部分テンプレートに記述しています。
remote: trueでHTMLリクエストでなく、Javascriptリクエストがfavoritesコントローラーに送られます。

books/_index.html.erb
.
.
<tbody>
    <% books.each do |book| %>
      <tr>
        <td><%= link_to(book.user) do %>
          <%= image_tag book.user.get_profile_image, size:'50x50' %>
          <% end %>
        </td>
        <td><%= link_to book.title,book %></td>
        <td><%= book.body %></td>
          <td id="favorite_btn_<%= book.id %>">
            <%= render "favorites/btn", book: book %>
          </td>
      </tr>
    <% end %>
  </tbody>
  .
  .

<td id="favorite_btn_<%= book.id %>">、後のjs.erbファイルの記述に更新したい箇所の指定が必要となるため、tdタグにHTMLのidで名前を付けます。

books/show.html.erb
<h2>Book detail</h2>
<table class='table'>
  ・
  ・
  ・
    <td id="favorite_btn_<%= @book.id %>">
      <%= render "favorites/btn", book: @book %>
    </td>
  ・
  ・
  ・
</table>

showページにも同様の記述をします。

リダイレクト先の削除

favorites_controller.rb
class FavoritesController < ApplicationController

  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

end

リダイレクト先を削除&先述したremote: trueでJavascriptリクエストを行ったことにより、createアクション実行後は、create.js.erbファイルに、
destroyアクション実行後はdestroy.js.erbファイルに遷移します。

jsファイルの作成

create.js.erb
$("#favorite_btn_<%= @book.id %>").html("<%= j(render 'favorites/btn', book: @book) %>");
destroy.js.erb
$("#favorite_btn_<%= @book.id %>").html("<%= j(render 'favorites/btn', book: @book) %>");

所感

今日は<%= @book.id %>を<% @book.id %>(=抜け)したり、
bookを@bookにしなかったりで手こずりました。人の助けを借りながらエラー解決すると解決の道筋のたどり方が分かってすごく勉強になりますね!かっこよくエラー対応できるエンジニアになりたいものです。

参考にしたページ

sayaさん

Discussion