いいね機能を非同期通信で実装してみた

![ajax.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641744/71c3b83c-0019-70c2-dc50-14b925cfce89.gif)

#はじめに
すでにたくさんの記事が出ていますが、自分の備忘録的に書きたいと思います。
#非同期通信のメリット
個人的に「なぜその技術が使われているのか」を先に学習しておくことで、
目的がはっきりするため理解がはやい、、、気がします。

###１. ページを遷移することなく、ページの一部だけを更新できる。
いいねのたびにページが遷移されていては正直かなりわずらわしいかなと思います。
ですが非同期通信を用いることで、__ページ遷移をすることなく、コメントができたり、いいねができたり、ユーザ編集ができたりするんです！__

#実装！
###手順① サーバーにJS形式のリクエストを送る
まず、非同期通信でない場合、いいね実行時のターミナルは以下の挙動です。
![スクリーンショット 2020-10-29 17.03.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641744/ed30bd31-22f3-b1af-3123-73f108fd948a.png)
画像の赤丸部分にリクエストの形式が出力されます。
この場合はHTML形式の通信になっているということですね！

こいつをJS形式にしたい、、、ということです！

```views:_favorites.html.erb
<%= link_to post_favorites_path(post), method: :DELETE, remote: true do %>
```

このように、いいねボタンのリンクに remote: true を追記してあげることでJS形式のリクエストを送ることができます。
![スクリーンショット 2020-10-29 17.15.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641744/69997f72-fa9e-43fb-efc7-99d06f815f66.png)


###手順② いいねボタンの部分テンプレートを作成する
非同期通信を実装するためには、変更部分を部分テンプレートにする必要があります。
具体的には、部分的に更新したい「いいね」の箱を用意して、
「いいね」しているか、していないかという状態で表示を切り替えるイメージです。

```views:views/posts/_favorites.html.erb
  <% if post.favorited_by?(current_user) %>
    <%= link_to post_favorites_path(post), method: :DELETE, remote: true do %>
      <span class="btn btn-danger">いいね外す</span>
    <% end %>
  <% else %>
    <%= link_to post_favorites_path(post), method: :POST, remote: true do %>
      <span class="btn btn-primary">いいねする</span>
    <% end %>
  <% end %>
```

部分テンプレート views/posts/_favorites.html.erb を作成して、
いいねボタンの部分をこちらに移します。
そして元のindex.htmlで先程作成した部分テンプレートを呼び出します。

```views:views/posts/index.html.erb
<div class="main_contents">
    <% @posts.each do |post| %>
        <div class="post_contents">
          <h2><%= link_to post.title, post_path(post.id) %></h2>
          <%= post.content %>

         <!-- ↓追加(部分的に更新したい場所)↓ -->
          <div id="favorite-<%= post.id %>">
             <%= render 'posts/favorites', post: post %>
          </div>
         <!-- ↑ここまで↑ -->
        </div>
  <% end %>
</div>
```

###手順③ js.erbファイルを作成する
HTML形式リクエストの場合、viewファイルは __views/コントローラ名/アクション名.html.erb__
のファイルを呼び出します。

しかし、JS形式のリクエストの場合、 __views/コントローラ名/アクション名.js.erb__
のファイルを呼び出します。

今回は、favoritesコントローラーの、create,destroyアクションを使用していいね機能を実装してますので、
__views/favorites/create.js.erb__　と　__views/favorites/destroy.js.erb__ 
ファイルを作成します。

```ruby:views/favorites/create.js.erb
 #id="favorite-<%= @post.id %>"この部分のHTMLだけ、renderで部分的に更新するという処理です
$("#favorite-<%= @post.id %>").html("<%= j(render 'posts/favorites',  post: @post ) %>");
```
```ruby:views/favorites/destroy.js.erb
$("#favorite-<%= @post.id %>").html("<%= j(render 'posts/favorites',  post: @post ) %>");
```

###手順④ コントローラーのリダイレクトを削除
```ruby:controllers/favorites_controller.rb
    def create
      @post = Post.find(params[:post_id])
      favorite = current_user.favorites.build(post_id: @post.id)
      favorite.save
      redirect_to root_path #←この行を削除
    end

    def destroy
      @post = Post.find(params[:post_id])
      favorite = current_user.favorites.find_by(post_id: @post.id)
      favorite.destroy
      redirect_to root_path #←この行を削除
    end
```

#完成！
以上の手順でいいね機能の非同期化が実装できます！

##参考
[Ajax(非同期通信)についてわかりやすさ重視でまとめてみた(Rails使用のデモ付)
](https://qiita.com/__tambo__/items/409ccf256e84017ea307)