【発展】お気に入りに登録を非同期にしよう!


前回の記事の発展的な内容にになります。

上記のお気に入り機能が実装されている前提で話を進めていきます。

完成イメージ

ビューファイルの編集

link_toメソッドにremote: trueを追加します。

app/views/recipes/show.html.erb
#中略
<% if current_user != @recipe.user %>
  <div class="recipe-like">
    <% if @recipe.liked_by(current_user).blank? %>
      <%= link_to "お気に入りに保存", recipe_likes_path(@recipe), method: :post, remote: true, class: "btn btn-success btn-sm" %> #編集
    <% else %>
      <%= link_to "保存済み", recipe_like_path(@recipe,@recipe.liked_by(current_user)), method: :delete, remote: true, class: "btn btn-outline-success btn-sm" %> #編集
    <% end %>
  </div>
<% end %>
#以下略

コントローラーの編集

redirect_toからrespond_toに変更します。
respond_to :jsと記述することによってjs形式でレスポンスを返すようになり、app/views/コントローラ名/アクション名.js.erbが出力されます。

app/controllers/likes_controller.rb
class LikesController < ApplicationController

  def create
    @like = current_user.likes.build(like_params)
    @recipe = @like.recipe
    if @like.valid?
      @like.save
      respond_to :js #編集
    end
  end

  def destroy
    @like = Like.find(params[:id])
    @recipe = @like.recipe
    if @like.destroy
      respond_to :js #編集
    end
  end

js.erbファイルの作成、編集

respond_to :jsで出力するファイルを作成していきます。

ターミナル
touch app/views/likes/{create.js.erb,destroy.js.erb}

それではcreate.js.erbから編集してきましょう。

.recipe-likeでclassを取得し.htmlの()内のHTMLに置き換えます。

app/views/likes/create.js.erb
$('.recipe-like').
html('<%= link_to "保存済み", recipe_like_path(@recipe,@recipe.liked_by(current_user)), method: :delete, remote: true, class: "btn btn-outline-success btn-sm" %>');

同じ要領でdestroy.js.erbも編集します。

app/views/likes/destroy.js.erb
$('.recipe-like').
html('<%= link_to "お気に入りに保存", recipe_likes_path(@recipe), method: :post, remote: true, class: "btn btn-success btn-sm" %>');

以上で実装完了です。
それでは挙動を確認してみましょう。