【Ruby on rails】JavaScript 非同期通信のコメント機能でエラーメッセージを出す　バリデーション

<h2>初めに</h2>
非同期通信でのコメント機能は実装ずみで、「40１字以上のコメント」はNGというバリデーションは、
かけていたものの、エラーメッセージが出るようにしていませんでした・・・。
少し実装に苦労はしたものの、非同期通信への理解が深まったのでまとめていきます！！

![スクリーンショット 2021-08-27 11.11.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633266/44f28078-ac76-b295-e17d-d303e000d722.png)

<h2>バリデーションをかけておく</h2>

```perl:app/models/post_comment.rb
class PostComment < ApplicationRecord
  default_scope -> { order(created_at: :desc) }
  # あるコメントに紐づくユーザーも記事も１
  belongs_to :user
  belongs_to :post

  validates :comment, presence: true, length: { maximum: 400 }
end
```
一応マイグレーションファイルも。

```perl:db/migrate/20210801122808_create_post_comments.rb
class CreatePostComments < ActiveRecord::Migration[5.2]
  def change
    create_table :post_comments do |t|
      t.text :comment, null: false
      t.integer :user_id,null: false
      t.integer :post_id,null: false

      t.timestamps
    end
  end
end
```

```perl:app/views/post_comments/_comment.html.erb
 <%= form_with(model:[post, post_comment], remote: true) do |f| %>
      <%= f.text_area :comment, rows:'2',placeholder: "感想や疑問点をコメントで伝えましょう",required: true,class:"form-control" %>
      <%=f.submit "コメントする",class:"mt-2 btn btn-outline-secondary btn-block btn-sm"%>
```

とりあえず、ここまでやると空欄での投稿に対しては以下のように出てきます。
ただ、４０１文字打ってもバリデーションには引っかかるものの何も出てこないという状況です。

![スクリーンショット 2021-08-27 10.31.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633266/93843d94-aed0-f1a6-ab4a-2150e52b8ff3.png)

<h2>コントローラーで保存できなかった場合の記述を書く！</h2>

```perl:controllers/post_comments_controller.rb
  def create
    post = Post.find(params[:post_id])
    @comment = current_user.post_comments.new(post_comment_params)
    @comment.post_id = post.id
    @post = Post.find(params[:post_id])
    if @comment.save
      # ユーザーステータス無効で、投稿者とコメント者が等しいとき
      if current_user != @post.user && @post.user.is_valid == true
        @post.create_notification_by(current_user)
      end
      @post_comment = PostComment.new
    else
      render 'error'
    end
  end
```

通知機能も実装してるのでわかりにくくなっているかもしれません・・・・すみません。
コメントがバリデーションに引っかかってしまい保存されなかったら、
```render 'error'```というところがポイントです！！！

さてrender先にいきます。

<h2>error.js.erb</h2>

```perl:views/post_comments/error.js.erb
$("#comments-error").html("<%= j(render 'layouts/errors', obj: @comment) %>");
```

コメントが401字でバリデーションに引っかかってるので、@commentの持ってる値としては
”false"になっています。

そしてここの記述としては、idが```comments-error```となっているどこかに、
```<%= j(render 'layouts/errors', obj: @comment) %>```を渡す:metal:という意味
です。
ちなみに'layouts/errors'の中身はこんな感じになっています。

```erb
<% if obj.errors.any?%>
<div class="text-center" style="color:red;">
<%=obj.errors.count %>件のエラーが発生しました。<br>
<% obj.errors.full_messages.each do |message| %>
    <%= message %>
  <% end %>
</div>
<% end %>
```

さてこのエラー文を差し込む、```id = comments-error```の箇所を作りましょう。

<h2>エラーメッセージを出す</h2>


```perl:app/views/post_comments/_comment.html.erb
#ここです！！！！
<div id ="comments-error"></div>
      <%= form_with(model:[post, post_comment], remote: true) do |f| %>
      <%= f.text_area :comment, rows:'2',placeholder: "感想や疑問点をコメントで伝えましょう",required: true,class:"form-control" %>
      <%=f.submit "コメントする",class:"mt-2 btn btn-outline-secondary btn-block btn-sm"%>
      <% end %>
```

```<div id ="comments-error"></div>```という箇所を作成しました。

これでコメント欄のすぐ上にエラーメッセージができます。

![スクリーンショット 2021-08-27 11.11.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633266/44f28078-ac76-b295-e17d-d303e000d722.png)

<h2>まとめ：非同期通信のエラーメッセージの流れ</h2>

```
コメントがバリデーションに引っ掛かり保存されない
↓
errorのjsファイルに飛ぶ
↓
jsファイルは指定されてるidに、html以下を差し込む
↓
該当のidが記載されてる箇所で、html以下を受け取り表示する。
要するに、普段は
<div id ="comments-error"></div>なってるところが、
<div id ="comments-error">render 'layouts/errors', obj: @comment</div>
になってくれて、エラー文が出てくると！
```

<h2>そもそも非同期通信とは..</h2>
最後に書くことはでなはいですが、簡単にまとめていきます。
簡単にいうと「データを送信したら、もう画面を書き換えてもらう」ということです。
サーバーからの結果は待ちません。
通常であればちゃんと応答待ちますが、非同期通信は待ちません！
メリットとしては待つ必要が無いから、早いということです。
サーバーが処理してる間に、操作ができます。
「あとやっといて〜」って感じでしょうか。

<h2>最後に</h2>

非同期通信がうまくいかないときって、大体スペルミスのような気がしますので、
スペルミスにご注意ください！！！！！！