2
0

More than 3 years have passed since last update.

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

Last updated at Posted at 2021-08-27

初めに

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

スクリーンショット 2021-08-27 11.11.49.png

バリデーションをかけておく

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

  validates :comment, presence: true, length: { maximum: 400 }
end

一応マイグレーションファイルも。

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
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"%>

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

スクリーンショット 2021-08-27 10.31.30.png

コントローラーで保存できなかった場合の記述を書く!

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先にいきます。

error.js.erb

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'の中身はこんな感じになっています。

<% 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の箇所を作りましょう。

エラーメッセージを出す

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

まとめ:非同期通信のエラーメッセージの流れ

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

そもそも非同期通信とは..

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

最後に

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

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0