[Ajax]コメント機能を非同期通信にした

# はじめに
本記事では、コメント機能を非同期通信にした方法を記述しています。

過去に、いいね機能とフォロー機能を非同期通信にしている記事も書いておりますので、
参照ください。

https://qiita.com/mkato1013/items/9ee39a7675371aa585ce

https://qiita.com/mkato1013/items/25f2a5abcd201a6a4072

## 前提
コメント機能は同期通信にはできる状態です。
該当箇所のみの記載です。

# コード

## コントローラー
food(投稿した食べ物)の詳細画面（show）にてコメントできる仕様です。
show内で完結するので、newメソッドもあります。
createメソッドでもコメントできましたが、
コメントはcommentテーブルに保存するので、newの方が良いと思っています。


```foods_controller.rb

省略

  def show
    @food = Food.find(params[:id])
    @like = Like.new
    @comment = Comment.new
    @comments = @food.comments.order("created_at DESC")
  end

省略

```
ここも特に同期通信と変わりません。
`merge(user_id: current_user.id ,food_id: params[:food_id])`
ここ忘れないように。

```comments_controller.rb
class CommentsController < ApplicationController
  def create
    @food = Food.find(params[:food_id])
    @comment = Comment.create(comment_params)
    @comments = @food.comments.order("created_at DESC")
  end

  private
  def comment_params
    params.require(:comment).permit(:text).merge(user_id: current_user.id ,food_id: params[:food_id])
  end
end
```

## モデル
同期通信と変わりません。
`belongs_to`とか`has_many`などですので、省略します。

## ビュー
記事を書いててミスを見つけました。
`locals`が`lacals`になっていました、、、
あっぶね〜😇

・・・

`<div class="food-comments-contents-<%= @food.id %>">`
クラス名に`-<%= @food.id %>`を入れないと何の投稿に対するコメントなのか
わかりませんので、ここが抜けているとリロードしないとコメントが反映されないと思います。
コードが長いので、部分テンプレートにしています。

`foods/show.html.erb`

```erb
省略

<h2 class="show-food-comments-title">Comments !</h2>
  <div class="food-comments-contents-<%= @food.id %>">
    <%= render partial:"comments/comment", locals: {food: @food} %>
  </div>

省略
```
`comments/_comment.html.erb`
3行目に`remote: true`を入れます。
これにより非同期通信が可能になり、リクエストがjs形式になります。

```erb
<div class="comments-comment-contents">
  <% if user_signed_in? %>
    <%= form_with(model: [@food, @comments],url: food_comments_path(@food,@comment), remote: true) do |f| %>
      <%= f.text_area :text, placeholder: "コメントする", rows: "2", class: "food-comment-textbox" %>
      <%= f.submit "SEND" ,class: "food-comment-textbox-send" %>
    <% end %>
    <ul class="show-food-comments">
      <% @comments.each do |comment| %>
        <li class="show-food-comment">
          <div class="comment-food-post-users">
          <div>
          <%= link_to user_path(comment.user_id) do %>
            <% if comment.user.icon.present? %>
              <%= image_tag comment.user.icon, class: "icon-img" %>
            <% else %>
              <i class="fas fa-user-circle"></i>
            <% end %>
          <% end %>
          </div>
          <div>
          <%= link_to user_path(comment.user_id),class: "comment-food-post-user" do %>
            <%= comment.user.nickname %>
          <% end %>
          <%= comment.text %>
          </div>
          </div>
        </li>
      <% end %>
    </ul>
  <% else %>
    <p class="please-login">コメント閲覧・投稿する際は<br/>「新規登録」「ログイン」をお願いします</p>
  <% end %>
</div>
```
`comments/create.js.erb`
リクエストがjs形式のため、
ファイル名は`create.js.erb`になります。
先ほど`foods/show.html.erb`にて作った
クラス`food-comments-contents-<%= @food.id %>`が
また部分テンプレートの`comments/comment`に行きます。
これで`create＝コメントした`ということが反映されます。

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

以上です。
いいねやフォローに比べればまだ簡単なように思えます。

# 終わりに
私が作成したアプリはコメント機能を非同期化しています。
昨今のアプリでコメント機能が非同期化していないアプリはありませんね。
必ず導入するべきだと思います。

また、いいね機能やフォロー機能を非同期化していれば、
少し考えればコメント機能の非同期化は容易ですので、
いいね機能とフォロー機能の非同期化もマスターしたいところです。

以下参考サイトです。
[[Rails]Ajaxを用いて非同期でコメント機能の実装](https://qiita.com/yuto_1014/items/c7d6213139a48833e21a)
[Railsアプリに非同期通信のコメント機能を実装](https://qiita.com/anago1030/items/364455ee556337dd1fc7)

明日も頑張ります！！