Rails 非同期通信のコメント機能にエラーメッセージを表示
はじめに
非同期通信でのコメント機能は実装済みです!
「401字以上のコメント」はNGというバリデーションをかけて、
そこにエラーメッセージ自体も非同期で表示できるようにします!🏋🏻
1.バリデーション
class PostComment < ApplicationRecord
belongs_to :user
belongs_to :book
+ validates :comment, presence: true, length: { maximum: 400 }
end
一応マイグレーションファイルも編集
class CreatePostComments < ActiveRecord::Migration[6.1]
def change
create_table :post_comments do |t|
+ t.text :comment, null: false
t.integer :user_id, null: false
t.integer :book_id, null: false
t.timestamps
end
end
end
<div class="mt-3">
<%= form_with model: [ book, post_comment ], local: false do |f| %>
<%= f.text_area :comment, placeholder: "コメントをここに",required: true, class: "w-100" %><br>
<%= f.submit "送信" %>
<% end %>
</div>
ここまでの記述で空欄の投稿に対しては以下のように表示されます。
しかし、401文字打ってもバリデーションには引っかかるものの何も出てこないという状況です。
2.コントローラー
コントローラーで保存できなかった場合の記述を書きます!
コメントが(バリデーションに引っかかってしまい)保存されなかったら、
render 'error' が読み込まれます💡
class PostCommentsController < ApplicationController
def create
@book = Book.find(params[:book_id])
@user = @book.user
@post_comment = current_user.post_comments.new(post_comment_params)
@post_comment.book_id = @book.id
+ unless @post_comment.save
+ render 'error'
+ end
end
ifとunlessの違い
ifとunlessは条件分岐に使われるキーワードであり、基本的には反対の条件を表します。
ifは、条件がtrueの場合に処理を実行し、falseの場合は処理をスキップします。
一方、unlessは条件がfalseの場合に処理を実行し、trueの場合は処理をスキップします。
3.render先の記述(error.js.erb)
$("#comments-error").html("<%= j(render 'layouts/errors', obj: @post_comment) %>");
コメントが401字でバリデーションに引っかかっているので、saveメソッドがfalseを返し、
@post_commentの持ってる値としては”false"になっています。
$("#comments_error")でid = "comments_error"をターゲットとし、render 'layouts/errors'で指定しているlayouts/_errors.html.erbの内容で書き換えています。
ちなみにlayouts/_errors.html.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 %>
4.エラーメッセージを表示させる
先ほどのエラー文を表示させるために、id = comments-errorを差し込む!
+<div id ="comments-error"></div>
<div class="mt-3">
<%= form_with model: [ book, post_comment ], local: false do |f| %>
<%= f.text_area :comment, placeholder: "コメントをここに",required: true, class: "w-100" %><br>
<%= f.submit "送信" %>
<% end %>
</div>
<div id ="comments-error"></div>
という箇所を作成しました。
これでコメント欄のすぐ上にエラーメッセージを表示されます!!
非同期通信のエラーメッセージ表示の流れ
コメントがバリデーションに引っかかり保存されない
⇩
errorのjsファイルに飛ぶ
⇩
jsファイルは指定されているidにhtml以下を差し込む
⇩
該当のidが記載されている箇所で、html以下を受け取り表示する
普段は
<div id ="comments-error"></div>なっているところが、
エラーになると
<div id ="comments-error">render 'layouts/errors', obj: @post_comment</div>
になってくれて、エラー文が表示される!
エラーメッセージの消去
エラーメッセージが表示された後に、新しい投稿をしてもエラーメッセージが消えない問題が発生したのでコードを追加しました!
create.jsに、comment-errorのlengthがあった時に、
comments-errorを消す記述を追記!
$("#post-comments").html("<%= j(render "post_comments/show", book: @book) %>");
$("#comment_count").html("<%= @book.post_comments.count %>")
$("textarea").val('');
+if ($("#comments-error").length) {
+ $("#comments-error").remove();
+}
これで、新しいコメントが投稿された際に、エラーメッセージが残らなくなりました💪🏻
🌱empty()メソッドとremove()メソッドの違いについて
🌱参考にさせていただいた記事
ややこしい〜〜〜が、
非同期通信について少し理解が深まったかも?
地道に積み重ねて理解していこう🏋🏻
Discussion