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

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

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

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

解決済

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

izu_reco
izu_reco

総合スコア2

Ruby on Rails 6

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

1回答

0評価

0クリップ

200閲覧

投稿2022/05/04 07:19

編集2022/05/05 15:32

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

Version

Ruby on Rails 6

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

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

該当のソースコード

① コントローラー

Ruby

class FoodsController < ApplicationController def new @form = Form::FoodCollection.new(params[:box_id]) end def create @form = Form::FoodCollection.new(food_collection_params) if @form.save == true redirect_to root_path, notice: "商品を登録しました" else render :new end end private def food_collection_params params.require(:form_food_collection) .permit(:food_title, :number_title, :purchase_date, :expiry_date, :price, :give_id) .merge( box_id: params[:box_id] ) end end

②Formオブジェクトモデル

Ruby

# Base class Form::Base include ActiveModel::Model include ActiveModel::Callbacks include ActiveModel::Validations include ActiveModel::Validations::Callbacks end # Baseを継承したFoodCollectionモデル class Form::FoodCollection < Form::Base FORM_COUNT = 3 #ここで、作成したい登録フォームの数を指定 attr_accessor( :foods, :food_title, :number_title, :purchase_date, :expiry_date, :price, :give_id, :box_id ) with_options presence: true do validates :food_title validates :number_title validates :purchase_date validates :expiry_date validates :price validates :give_id end # 初期化メソッド def initialize(box_id, attributes = []) if attributes.present? self.foods = attributes.map do |value| Food.new( food_title: value["food_title"], number_title: value["number_title"], purchase_date: value["purchase_date"], expiry_date: value["expiry_date"], price: value["price"], give_id: value["give_id"], box_id: value["box_id"] ) end else self.foods = FORM_COUNT.times.map { Food.new } end end def persisted? false end def save is_success = true Food.transaction do self.foods.each do |result| is_success = false unless result.save end raise ActiveRecord::RecordInvalid unless is_success end rescue p 'error' ensure return is_success end

③View

Ruby

<div class="items-sell-main"> <h2>冷蔵庫に入っている食材を入力しよう!</h2> <div id="div_default"><h2>上の食材カテゴリを選んでね</h2> </div> <%= form_with model: @form, url: box_foods_path, method: :post, local: true do |fr| %> <%= render 'shared/error_messages', model: fr.object %> <div id="div_fish"> <%# <%= render partial: 'shared/fields_for', locals:{ form: form } %> <h2>選択されている食材カテゴリ : <i class="fa-solid fa-fish"></i>Fish </h2> <table class="item-table"> <thead> <tr class="item-tr"> <th>魚の食材名</th> <th>個数</th> <th>購入日</th> <th>消費期限</th> <th>購入価格</th> <th>不要チェック</th> </tr> </thead> <tbody> <%= fr.fields_for :foods do |f| %> <tr> <td><%= f.text_field :food_title %></td> <td><%= f.number_field :number_title, min: 1, max: 99 %></td> <td><%= f.date_field :purchase_date %></td> <td><%= f.date_field :expiry_date %></td> <td><%= f.text_field :price %></td> <td><%= f.check_box :give_id, {}, "true", "false" %></td> </tr> <% end %> </tbody> </table> </div>

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

Ruby

<% if model.errors.any? %> <div class="error-alert"> <ul> <% model.errors.full_messages.each do |message| %> <li class='error-message'><%= message %></li> <% end %> </ul> </div> <% end %>

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

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

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

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

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

ruby

[25] pry(#<#<Class:0x00007fb8f7ec4318>>)> @form.errors => #<ActiveModel::Errors:0x00007fb8e0da9a08 @base= #<Form::FoodCollection:0x00007fb91034b658 @box_id="38", @errors=#<ActiveModel::Errors:0x00007fb8e0da9a08 ...>, @foods= [#<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>, #<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>, #<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>]>, @details={}, @messages={}>

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

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

winterboum

2022/05/04 23:33

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

2022/05/05 01:48

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

まだ回答がついていません

会員登録して回答してみよう

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

ただいまの回答率
87.20%

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

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

質問する

関連した質問

同じタグがついた質問を見る

Ruby on Rails 6

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