質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%

Q&A

解決済

1回答

2580閲覧

Rails6_バリデーションにかかったときのエラーメッセージを表示できない。

shisoshiso

総合スコア17

1グッド

1クリップ

投稿2022/02/17 13:53

編集2022/02/17 14:02

前提・実現したいこと

バリデーションに引っかかった時にエラーメッセージを表示したいのですが、表示されません。

参考記事
バリデーションの実装
https://qiita.com/nakanishi03/items/d1be27c74c98855423ab
デバッグ方法
https://techtechmedia.com/error-messages-validation-rails/

イメージ説明

models/event.rb
バリデーションは、下記を設定しています。
未入力で「Create Event」をクリックすると、全5項目がバリデーションエラーを起こします。

ruby

1class Event < ApplicationRecord 2 validates :name, length: { maximum: 50 }, presence: true 3 validates :place, length: { maximum: 100 }, presence: true 4 validates :content, length: { maximum: 2000 }, presence: true 5 validates :start_at, presence: true 6 validates :end_at, presence: true 7 # カスタムバリデーション 8 # https://qiita.com/yutas-8/items/8b6b4b6ce876ad2cf26b 9 validate :start_at_should_be_before_end_at 10 11 private 12 13 # 開始時間は終了時間よりも前の時間 14 def start_at_should_be_before_end_at 15 return unless start_at && end_at 16 17 if start_at >= end_at 18 errors.add(:start_at, "は終了時間よりも前に設定して下さい") 19 end 20 end 21end

controllers/events_controller.rb
バリデーションに引っかかり保存できなかったときは、views/events/new.html.slimをレンダリングします。

ruby

1class EventsController < ApplicationController 2 def new 3 @event = current_user.created_events.build 4 end 5 6 def create 7 @event = current_user.created_events.build(event_params) 8 9 if @event.save 10 redirect_to @event, notice: "作成しました" 11 else 12 render :new 13 end 14 end 15 16 private 17 18 def event_params 19 params.require(:event).permit( 20 :name, :place, :content, :start_at, :end_at 21 ) 22 end 23end

views/events/new.html.slim
バリデーションエラーを起こした時は、= render "shared/errors", model: f.objectでエラーメッセージを差し込みます。

ruby

1- now = Time.zone.now 2 3h1.mt-2 イベント作成 4 5= form_with(model: @event, class: "form-horizontal") do |f| 6 = render "shared/errors", model: f.object 7 .form-group 8 = f.label :name 9 = f.text_field :name, class: "form-control" 10 .form-group 11 = f.label :place 12 = f.text_field :place, class: "form-control" 13 .form-group 14 = f.label :start_at 15 div 16 = f.datetime_select :start_at, start_year: now.year, end_year: now.year + 1 17 .form-group 18 = f.label :end_at 19 div 20 = f.datetime_select :end_at, start_year: now.year, end_year: now.year + 1 21 .form-group 22 = f.label :content 23 = f.text_area :content, class: "form-control", row: 10 24 = f.submit class: "btn btn-primary"

- if model.errors.any?で@event.errors.any?がtrueの時だけ表示するようにしています。
views/shared/_errors.html.slim

ruby

1- if model.errors.any? 2 .alert.alert-danger 3 ul.mb-0 4 - model.errors.full_messages.each do |message| 5 li = message

自分で調べたことや試したこと

最低限以下のことはチェックしましたが、解決に至りませんでした。

  • _errors.html.slimのレンダリングは正しくできているか?

 - if model.errors.any?をコメントアウトして、適当なテキストを追加するとブラウザで表示できることを確認できたため、レンダリングすることはできている。

  • バリデーションは動作している?

 binding.pryでデバッグしてみましたが、正しく動作している。デバッグ詳細は下記。Nameなど全て未入力です。

ruby

1 6: def create 2 7: @event = current_user.created_events.build(event_params) 3 8: 4 9: if @event.save 5 10: redirect_to @event, notice: "作成しました" 6 11: else 7 12: 8 => 13: binding.pry 9 14: 10 15: render :new 11 16: end 12 17: end 13 14[1] pry(#<EventsController>)> @event.errors.any? 15=> true 16[2] pry(#<EventsController>)> @event.errors.full_messages 17=> ["Name can't be blank", "Place can't be blank", "Content can't be blank", "Start at は終了時間よりも前に設定して下さい"]
  • slim記法が間違っている?

下記記事を参考にチェックしましたが、問題ない。
https://pikawaka.com/rails/slim

現状完全に手詰まり状態になってしまっているため、少しでも気になる点があればご教授いただけるとありがたいです。
よろしくお願いいたします。

使っているツールのバージョンなど補足情報

Rails 6.0.3
ruby 2.6.5
slim-rails (3.3.0)

補足ですが、こちらはパーフェクト Ruby on Railsの演習の一部です。
書籍ではSJRで実装されていますが、その方法でもうまくいかなかった為、以前実装したことのある今回の手法を試しています。(今回もうまくいっていないのですが。。)

shinoharat👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

【案1】
form_with はAjaxを前提に動作するため、javascript で ajax:success を拾ってエラーメッセージを描画する必要があります。

Rails ガイドの

  • Rails で JavaScript を利用する > 3 組み込みヘルパー > 3.1 remote要素
  • Rails で JavaScript を利用する > 4 サーバー側で考慮すべき点 > 4.1 シンプルな例

辺りを参考にするとイイ感じになると思います。

https://railsguides.jp/working_with_javascript_in_rails.html

--

【案2】
ぶっちゃけ案1は面倒くさいので、特にこだわりが無い場合は :local オプションを使ってAjaxをoffにしちゃうと楽です。1行だけの変更で済みます。

diff

1- = form_with(model: @event, class: "form-horizontal") do |f| 2+ = form_with(model: @event, local: true, class: "form-horizontal") do |f|

投稿2022/02/18 07:01

編集2022/12/19 04:12
shinoharat

総合スコア1676

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shisoshiso

2022/02/19 09:19

ご回答・具体的な案を頂きありがとうございます。解決しました! 教えて頂いた2つのやり方で実装することができました。また参考サイトもありがとうございます。非常に勉強になりました。今後はHTTP通信がどのように行われているのか、意識して実装することを心がけたいと思います。 以下、実装したコードです。(同じような悩みを抱える方へ向けて) 案1 Ajaxリクエストに対してrespond_toでエラーメッセージを作って返すやり方。 ```ruby # events/new.html.slim # renderの代わりにJavaScriptを差し込むためのid=errorsを追加 = form_with(model: @event, class: "form-horizontal") do |f| #errors .form-group = f.label :name 略 # events_controller.rb # Ajaxリクエストにformat.jsで対応 def create @event = current_user.created_events.build(event_params) respond_to do |format| if @event.save format.html { redirect_to @event } else format.js end end end # events/create.js.erb # format.jsに対応するビューファイル。これを元にJavaScriptが生成され、クライアントに送信された後に実行 var errors = document.querySelector("#errors") # views/application/_errors.html.slimに書いたHTMLを利用 errors.insertAdjacentHTML("beforeend", "<%= j render("errors", errors: @event.errors) %>"); ``` 案2 Ajax無し。こちらのやり方は本当に楽ですね。 ```ruby = form_with(model: @event, local: true, class: "form-horizontal") do |f| ```
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問