[Ajax]いいね機能を非同期にした

# はじめに
本記事では、非同期通信についてを記述します。
本日実装しました。

## 前提
いいね機能は同期通信で実装しています。

また、オリジナルアプリ開発途中で不要なコードが多いので、
`省略は多め`ですが、該当箇所は記載します。

# いいね機能
### ビュー
いいねを表示しているビュー`index.html.erb`

`<div class="food-likes-<%= food.id %>">`にしないと、
`どのfood(投稿)に対するいいね`なのか分かりません。
試しに`-<%= food.id %>`を抜いたところ、
全部の投稿が同時にいいね出来る仕様になってしまいました。
ふと`localsメソッド`の意味を忘れたので、調べましたw
[【Rails】 部分テンプレートの使い方を徹底解説！](https://pikawaka.com/rails/partial_template)

```erb
省略

<% @foods.each do |food| %>
         
省略
              
  <div class="food-likes-<%= food.id %>">
     <%= render partial:"likes/like", locals: {food: food} %>
  </div>

省略

<% end %>

省略
```
### コントローラー
`@foods=~`に関しては前回の投稿を参照ください。

https://qiita.com/mkato1013/items/44b8a865d6c51ee61fb9

```foods_controller.rb
  def index
    @foods = Food.order("created_at DESC").where(user_id: [current_user.id,*current_user.following_ids]).where(created_at: from...to)
    @like = Like.new
  end
```
`createはいいね`、`destroyはいいね解除`になります。
同期通信の場合、endの前に`redirect to~`がありますが、必要ないので消します。

```likes_controller.rb
class LikesController < ApplicationController

  def create
    @food = Food.find(params[:food_id])
    @like = current_user.likes.create(food_id: params[:food_id])
  end

  def destroy
    @food = Food.find(params[:food_id])
    @like = Like.find_by(food_id: params[:food_id],user_id: current_user.id)
    @like.destroy
  end
end
```
### モデル

```food.rb
省略
  belongs_to :user
  has_many :likes
  has_many :liked_users, through: :likes, source: :user
省略
```

```like.rb
class Like < ApplicationRecord
  belongs_to :food
  belongs_to :user
  
  validates_uniqueness_of :food_id, scope: :user_id
end
```
### 部分テンプレートのビュー
`<%= render partial:"likes/like", locals: {food: food} %>`の`likes/like`

`remote: true`することで、
リクエストがjs形式になります。

注意点としては、`local :true`は消しましょう。

```erb
<h2 class="food-likes-index">KALIKE
  <%= food.likes.count %>
</h2>
<% if user_signed_in? %>
  <% if current_user.already_liked?(food) %>
    <%= link_to "いいねを取り消す", food_likes_path(food,@like), method: :delete, remote: true %>
  <% else %>
    <%= link_to "いいね", food_likes_path(food), method: :post, remote: true %>
  <% end %>
<% end %>
```
### js.erbファイル
リクエストがjsなので、`js.erb`でお出迎えです。
`create.js.erb`

```erb
$('.food-likes-<%= @food.id %>').html("<%= j(render partial: 'likes/like', locals: {food: @food}) %>")
```
`destroy.js.erb`

```erb
$('.food-likes-<%= @food.id %>').html("<%= j(render partial: 'likes/like', locals: {food: @food}) %>")
```

`j`については、`escape_javascript`の略です。
> escape_javascriptは、改行やエスケープ処理をしてくれます。
[【Rails】 remote: trueでフォーム送信をAjax実装する方法とは？
](https://pikawaka.com/rails/remote-true)


以上です。
いかがでしょうか。

# 終わりに
割と悩みました。
特に`js.erb`ファイルは初見だったので良い経験ができて楽しかったです。

いいねができたので、
フォロー機能とコメント機能も非同期にしてみようとコード書いてみたら、
そこそこすんなり（コメント機能はやや悩んだ）できました。

次回以降フォロー機能とコメント機能の非同期通信についても書こうと思います。

以下参考サイトです。
[【Rails】 remote: trueでフォーム送信をAjax実装する方法とは？](https://pikawaka.com/rails/remote-true)
[RailsとAjaxを使ったいいね機能の非同期通信](https://qiita.com/naota7118/items/e009eff939b5a764672d)
[Railsガイド](https://railsguides.jp/working_with_javascript_in_rails.html)
[JavaScriptで関数のエイリアスを作る方法を現役エンジニアが解説【初心者向け】](https://techacademy.jp/magazine/35296)
[HTML特殊文字のエスケープ](https://www.javadrive.jp/rails/template/index7.html)
[パーシャルをレンダリングする前にescape_javascriptを使用するのはなぜですか？](https://codehero.jp/javascript/1620113/why-escape-javascript-before-rendering-a-partial)

明日も頑張ります！！