0
1

axiosを使わないでいいね機能を非同期化

Posted at

こんにちは、普段はプログラミングスクールでメンターをやっている@takokkeです。

今回はいいね機能の非同期化手順を学習記録としてまとめてみました。axiosなどのjsライブラリを使わず、シンプルにjQueryだけで実装したいと思います

非同期処理の大まかな手順

  1. いいねボタンを押したら、javascriptリクエストがコントローラに送られる
  2. アクションがデータ処理を行い、いつもならhtml.erbにインスタンス変数を渡すが、今回はjs.erbへ渡す
  3. js.erbに記述したjsコードが、いいねボタンの部分だけ書き換える

ポイントは、いつもならコントローラで定義したインスタンス変数がhtml.erbに渡るのを、js.erbに渡すということです。

いいねボタンのHTMLを部分テンプレート化

いいねボタンの部分テンプレートを作成します。

app/views/favorites/_favorite-btn.erb
<% if book.favorited_by?(current_user) %>
  <%= link_to book_favorites_path(book.id), method: :delete, remote: true do %>
    <i class="fa fa-heart text-danger"><%= book.favorites.count %></i>
  <% end %>
<% else %>
  <%= link_to book_favorites_path(book.id), method: :post, remote: true do %>
    <i class="fa fa-heart text-primary"><%= book.favorites.count %></i>
  <% end %>
<% end %>

link_to内にremote; true を追加することで、
HTMLリクエストではなく、JavaScriptのリクエストがfavoritesコントローラに送られます。

呼び出し元にidを付与しよう

投稿一覧ページなどはidで変更したい部分を指定します。

app/views/books/index.html.erb
:
	省略
:	
<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%>

<td id="favorite_buttons_<%= book.id %>" >でid属性がbookのidによって変わるようにしています。これでいいねボタンを押した部分だけ変更できます。

コントローラで指定しているリダイレクト先を削除

app/controllers/favorites_controller.rb
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ファイルを探してくれます。

js.erbを作成使用

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

以上です

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1