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

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

新規登録して質問してみよう
ただいま回答率
85.49%
Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

1回答

2295閲覧

【Rails】Form入力に誤りがあった場合に、エラー文を表示させたい

izu_reco

総合スコア2

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2022/05/04 07:19

編集2022/05/05 01:47

はじめまして。
現在、1つのモデルに対して、一度の投稿で複数のレコードを登録する機能を実装しています。
もし入力ミスがあった場合、再度入力フォームに戻り、Validationエラーを表示させたいのですが、Formオブジェクトモデルのインスタンスのerrorsに、エラーメッセージが格納されていないからか、表示されません。お知恵をお借りしたく、何卒よろしくお願いします。

Version

Ruby on Rails 6

発生している問題・エラーメッセージ

  • 入力箇所にエラーがあった場合、「再度入力フォームに戻る」ことはできているが、validationエラーの文章が表示されない。

該当のソースコード

① コントローラー

Ruby

1class FoodsController < ApplicationController 2 def new 3 @form = Form::FoodCollection.new(params[:box_id]) 4 end 5 6 def create 7 @form = Form::FoodCollection.new(food_collection_params) 8 if @form.save == true 9 redirect_to root_path, notice: "商品を登録しました" 10 else 11 render :new 12 end 13 end 14 15 private 16 17 def food_collection_params 18 params.require(:form_food_collection) 19 .permit(:food_title, :number_title, :purchase_date, :expiry_date, :price, :give_id) 20 .merge( 21 box_id: params[:box_id] 22 ) 23 end 24end

②Formオブジェクトモデル

Ruby

1# Base 2class Form::Base 3 include ActiveModel::Model 4 include ActiveModel::Callbacks 5 include ActiveModel::Validations 6 include ActiveModel::Validations::Callbacks 7end 8 9# Baseを継承したFoodCollectionモデル 10class Form::FoodCollection < Form::Base 11 FORM_COUNT = 3 #ここで、作成したい登録フォームの数を指定 12 attr_accessor( 13 :foods, 14 :food_title, :number_title, :purchase_date, :expiry_date, :price, :give_id, 15 :box_id 16 ) 17 18 with_options presence: true do 19 validates :food_title 20 validates :number_title 21 validates :purchase_date 22 validates :expiry_date 23 validates :price 24 validates :give_id 25 end 26 27 # 初期化メソッド 28 29 def initialize(box_id, attributes = []) 30 if attributes.present? 31 self.foods = attributes.map do |value| 32 Food.new( 33 food_title: value["food_title"], 34 number_title: value["number_title"], 35 purchase_date: value["purchase_date"], 36 expiry_date: value["expiry_date"], 37 price: value["price"], 38 give_id: value["give_id"], 39 box_id: value["box_id"] 40 ) 41 end 42 else 43 self.foods = FORM_COUNT.times.map { Food.new } 44 end 45 end 46 47 def persisted? 48 false 49 end 50 51 def save 52 is_success = true 53 Food.transaction do 54 self.foods.each do |result| 55 is_success = false unless result.save 56 end 57 raise ActiveRecord::RecordInvalid unless is_success 58 end 59 60 rescue 61 p 'error' 62 ensure 63 return is_success 64 end

③View

Ruby

1 <div class="items-sell-main"> 2 <h2>冷蔵庫に入っている食材を入力しよう!</h2> 3 <div id="div_default"><h2>上の食材カテゴリを選んでね</h2> 4 </div> 5 6 <%= form_with model: @form, url: box_foods_path, method: :post, local: true do |fr| %> 7 <%= render 'shared/error_messages', model: fr.object %> 8 <div id="div_fish"> 9 <%# <%= render partial: 'shared/fields_for', locals:{ form: form } %> 10 <h2>選択されている食材カテゴリ : <i class="fa-solid fa-fish"></i>Fish </h2> 11 <table class="item-table"> 12 <thead> 13 <tr class="item-tr"> 14 <th>魚の食材名</th> 15 <th>個数</th> 16 <th>購入日</th> 17 <th>消費期限</th> 18 <th>購入価格</th> 19 <th>不要チェック</th> 20 </tr> 21 </thead> 22 23 <tbody> 24 <%= fr.fields_for :foods do |f| %> 25 <tr> 26 <td><%= f.text_field :food_title %></td> 27 <td><%= f.number_field :number_title, min: 1, max: 99 %></td> 28 <td><%= f.date_field :purchase_date %></td> 29 <td><%= f.date_field :expiry_date %></td> 30 <td><%= f.text_field :price %></td> 31 <td><%= f.check_box :give_id, {}, "true", "false" %></td> 32 </tr> 33 <% end %> 34 </tbody> 35 </table> 36 </div>

▼renderのエラーメッセージ部分

Ruby

1<% if model.errors.any? %> 2<div class="error-alert"> 3 <ul> 4 <% model.errors.full_messages.each do |message| %> 5 <li class='error-message'><%= message %></li> 6 <% end %> 7 </ul> 8</div> 9<% end %>

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

仮説① : saveメソッドで保存するとき、validationのエラー文が発生していない?

  • ②Formオブジェクトのsaveメソッドでbinding.pryを行ったところ、error文はちゃんと発生していた。

仮説② : Formオブジェクトだと、エラー文が更新されていかない?

  • 通常のモデルだと、エラー文は@モデルのインスタンス.errorsに格納されていく
  • Formオブジェクトでは、エラー文がerrorsに格納されない??
  • そうであれば、生成されたエラー文を手動で@インスタンス.errorsに格納しないといけない??
  • ▼@インスタンス.errorsの中身を確認したところ、ActiveModel::Errors:0x000~といったオブジェクトの格納は確認できますが、ここの値を更新する方法がわかりませんでした。

ruby

1[25] pry(#<#<Class:0x00007fb8f7ec4318>>)> @form.errors 2=> #<ActiveModel::Errors:0x00007fb8e0da9a08 3 @base= 4 #<Form::FoodCollection:0x00007fb91034b658 5 @box_id="38", 6 @errors=#<ActiveModel::Errors:0x00007fb8e0da9a08 ...>, 7 @foods= 8 [#<Food:0x00007fb910371b28 id: nil, food_title: "にしん", number_title: nil, purchase_date: nil, expiry_date: nil, price: nil, give_id: 0, box_id: 38, created_at: nil, updated_at: nil>, 9 #<Food:0x00007fb8e141c5c0 id: nil, food_title: "さけ", number_title: nil, purchase_date: nil, expiry_date: nil, price: nil, give_id: 0, box_id: 38, created_at: nil, updated_at: nil>, 10 #<Food:0x00007fb8e1427970 id: nil, food_title: "さば", number_title: nil, purchase_date: nil, expiry_date: nil, price: nil, give_id: 0, box_id: 38, created_at: nil, updated_at: nil>]>, 11 @details={}, 12 @messages={}>

長文かつ分かりにくい箇所があるかと思いますが、何卒よろしくお願いします。

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

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

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

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

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

winterboum

2022/05/04 23:33

情報が断片過ぎます。 controller、form、View を下手な編集抜きで載せてください。
izu_reco

2022/05/05 01:48

winterboumさん ご指摘ありがとうございます。 それぞれのファイルを記載し直しました。ご確認のほど、よろしくお願いします。
guest

回答1

0

ベストアンサー

<%= render 'shared/error_messages', model: fr.object %> の model すなわち fr.object は @form です。
<% model.errors.full_messages.each do |message| %> と書くと一見 model は ARモデルのインスタンスの様に見えますが、これは @formすなわちForm::FoodCollection です。

self.foods.each do |result| is_success = false unless result.save end

のとき error は result.errors に貯められます。@form.errors ではありません。
ということで <% if model.errors.any? %> は常に nil.any? となります。

で、とても勘違いしやすいので変数名から実体が想定できるようにしましょう。
result ではなく food、model ではなく food_collection、、、などなど

とした上で
food_collection.foods.each { |food| として、 food.errors を書き出しましょう。

投稿2022/05/05 04:12

winterboum

総合スコア23324

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

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

izu_reco

2022/05/05 06:32

winterboumさん ご指導ありがとうございます。 errorは`@form`に格納されるものと認識してましたが、正しくは@formの`それぞれのオブジェクト`ということですね。 上記の認識で考えれば、@form.errors つまり `if model.errors.any?`がなぜtrueにならないのか、クリアになりました。 また、`変数名から実態が想定できるよう`に名づけするよう心がけたいと思います。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問