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

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

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

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

Q&A

解決済

1回答

1335閲覧

createアクション失敗時のエラーメッセージ表示について

DRUSS

総合スコア10

Ruby on Rails

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

0グッド

0クリップ

投稿2022/06/28 02:41

編集2022/06/28 03:11

前提

Ruby on rails でメルカリのようなフリーマーケットアプリを作成しています。
出品(画像や説明などを含むデータを保存する)機能を実装中

実現したいこと

・createアクションでデータの保存に失敗した場合、出品画面に戻り、エラーメッセージを表示したい
・フォームに入力されていない項目があった場合、validatesに引っかかって、"〜can`t be blank"などのエラーメッセージが出ることを想定しています。

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

・データの保存に失敗し、出品画面に戻っているが、エラーメッセージは表示されない。

該当のソースコード

items_controller.rb
コントローラー

class ItemsController < ApplicationController def index end def new @item = Item.new end def create @post = Item.create(item_params) if @post.save redirect_to root_path else @item = Item.new(item_params) render :new end end private def item_params params.require(:item).permit(:title, :price, :description, :image, :category_id, :condition_id, :fee_id, :from_id, :ship_date_id, ) end end

new.html.erb
出品画面

<div class="items-sell-contents"> <header class="items-sell-header"> <%= link_to image_tag('furima-logo-color.png' , size: '185x50'), "/" %> </header> <div class="items-sell-main"> <h2 class="items-sell-title">商品の情報を入力</h2> <%= form_with model: @item, local: true do |f| %> ** <%# インスタンスを渡して、エラー発生時にメッセージが表示。%> ** <%= render 'shared/error_messages', model: f.object %>** <%# 商品画像 %> <div class="img-upload"> <div class="weight-bold-text"> 商品画像 <span class="indispensable">必須</span> </div> <div class="click-upload"> <p> クリックしてファイルをアップロード </p> <%= f.file_field :image, id:"item-image" %> </div> </div> <%# /商品画像 %> <%# 商品名と商品説明 %> <div class="new-items"> <div class="weight-bold-text"> 商品名 <span class="indispensable">必須</span> </div> <%= f.text_area :title, class:"items-text", id:"item-name", placeholder:"商品名(必須 40文字まで)", maxlength:"40" %> <div class="items-explain"> <div class="weight-bold-text"> 商品の説明 <span class="indispensable">必須</span> </div> <%= f.text_area :description, class:"items-text", id:"item-info", placeholder:"商品の説明(必須 1,000文字まで)(色、素材、重さ、定価、注意点など)例)2010年頃に1万円で購入したジャケットです。ライトグレーで傷はありません。あわせやすいのでおすすめです。" ,rows:"7" ,maxlength:"1000" %> </div> </div> <%# /商品名と商品説明 %> <%# 商品の詳細 %> <div class="items-detail"> <div class="weight-bold-text">商品の詳細</div> <div class="form"> <div class="weight-bold-text"> カテゴリー <span class="indispensable">必須</span> </div> <%= f.collection_select(:category_id, Category.all, :id, :name, {}, {class:"select-box", id:"item-category"}) %> <div class="weight-bold-text"> 商品の状態 <span class="indispensable">必須</span> </div> <%= f.collection_select(:condition_id, Condition.all, :id, :name, {}, {class:"select-box", id:"item-sales-status"}) %> </div> </div> <%# /商品の詳細 %> <%# 配送について %> <div class="items-detail"> <div class="weight-bold-text question-text"> <span>配送について</span> <a class="question" href="#">?</a> </div> <div class="form"> <div class="weight-bold-text"> 配送料の負担 <span class="indispensable">必須</span> </div> <%= f.collection_select(:fee_id, Fee.all, :id, :name, {}, {class:"select-box", id:"item-shipping-fee-status"}) %> <div class="weight-bold-text"> 発送元の地域 <span class="indispensable">必須</span> </div> <%= f.collection_select(:from_id, From.all, :id, :name, {}, {class:"select-box", id:"item-prefecture"}) %> <div class="weight-bold-text"> 発送までの日数 <span class="indispensable">必須</span> </div> <%= f.collection_select(:ship_date_id, Ship.all, :id, :name, {}, {class:"select-box", id:"item-scheduled-delivery"}) %> </div> </div> <%# /配送について %> <%# 販売価格 %> <div class="sell-price"> <div class="weight-bold-text question-text"> <span>販売価格<br>(¥300〜9,999,999)</span> <a class="question" href="#">?</a> </div> <div> <div class="price-content"> <div class="price-text"> <span>価格</span> <span class="indispensable">必須</span> </div> <span class="sell-yen">¥</span> <%= f.text_field :price, class:"price-input", id:"item-price", placeholder:"例)300" %> </div> <div class="price-content"> <span>販売手数料 (10%)</span> <span> <span id='add-tax-price'></span>円 </span> </div> <div class="price-content"> <span>販売利益</span> <span> <span id='profit'></span>円 </div> </span> </div> </div> <%# /販売価格 %> <%# 注意書き %> <div class="caution"> <p class="sentence"> <a href="#">禁止されている出品、</a> <a href="#">行為</a> を必ずご確認ください。 </p> <p class="sentence"> またブランド品でシリアルナンバー等がある場合はご記載ください。 <a href="#">偽ブランドの販売</a> は犯罪であり処罰される可能性があります。 </p> <p class="sentence"> また、出品をもちまして <a href="#">加盟店規約</a> に同意したことになります。 </p> </div> <%# /注意書き %> <%# 下部ボタン %> <div class="sell-btn-contents"> <%= f.submit "出品する" ,class:"sell-btn" %> <%=link_to 'もどる', root_path, class:"back-btn" %> </div> <%# /下部ボタン %> </div> <% end %> <footer class="items-sell-footer"> <ul class="menu"> <li><a href="#">プライバシーポリシー</a></li> <li><a href="#">フリマ利用規約</a></li> <li><a href="#">特定商取引に関する表記</a></li> </ul> <%= link_to image_tag('furima-logo-color.png' , size: '185x50'), "/" %> <p class="inc"> ©︎Furima,Inc. </p> </footer> </div>

_error_messages.html.erb
エラーメッセージのテンプレート

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

データ保存失敗時のターミナル

Started POST "/items" for ::1 at 2022-06-28 11:29:08 +0900 Processing by ItemsController#create as HTML Parameters: {"authenticity_token"=>"IFNZqjBaWbreGSvhbh62c5UYV2H6ZS9zlPdlVFcMpq3GTtU5sbYyZDV2ZFtXTCxVGFNzSM6Bmr5XSl3i6FpXIw==", "item"=>{"title"=>"", "description"=>"", "category_id"=>"1", "condition_id"=>"1", "fee_id"=>"1", "from_id"=>"1", "ship_date_id"=>"1", "price"=>""}, "commit"=>"出品する"} Rendering items/new.html.erb within layouts/application Rendered shared/_error_messages.html.erb (Duration: 1.7ms | Allocations: 175) Rendered items/new.html.erb within layouts/application (Duration: 15.8ms | Allocations: 5808) [Webpacker] Everything's up-to-date. Nothing to do Completed 200 OK in 110ms (Views: 97.6ms | ActiveRecord: 0.0ms | Allocations: 30869)

item.rb
itemモデル(varidates)

class Item < ApplicationRecord validates :title, presence: true validates :price, numericality:{greater_than_or_equal_to: 300, less_than_or_equal_to: 9999999} validates :fee_id, numericality: { other_than: 1 , message: "can't be blank"} validates :description, presence: true validates :category_id, numericality: { other_than: 1 , message: "can't be blank"} validates :condition_id, numericality: { other_than: 1 , message: "can't be blank"} validates :from_id, numericality: { other_than: 1 , message: "can't be blank"} validates :ship_date_id, numericality: { other_than: 1 , message: "can't be blank"} has_one_attached :image extend ActiveHash::Associations::ActiveRecordExtensions belongs_to :category belongs_to :condition belongs_to :fee belongs_to :from belongs_to :ship end

試したこと

・出品画面(new.html.erb)のフォームを正しく入力をすれば保存できることは確認できています。(Sequel Proでデータベースを直接確認しています。)

・出品画面(new.html.erb)のフォームで誤った入力または入力をしなかった場合、保存できないことは確認できています。(Sequel Proでデータベースを直接確認しています。)

・コントローラーの"if @post.save"を"if @post.save!"に変更してバリデーションが原因のエラーが発生することは確認できました。

・ユーザー登録機能も既に実装しており、エラーメッセージのテンプレート(_error_messages.html.erb)は同じものを使っていて、ユーザー登録に失敗した場合、ちゃんとエラー表示されているのでテンプレートに問題はない(?)

補足情報(FW/ツールのバージョンなど)

Rubyのバージョン
ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-darwin21]

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

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

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

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

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

maisumakun

2022/06/28 02:57

> データの保存に失敗した場合 どのような要因で失敗する状況でしょうか?
DRUSS

2022/06/28 03:05

ご質問ありがとうございます。 validateに引っかかって保存ができないというエラーを想定しています。 例えば、フォームの"title"に入力がない状態で保存をしようとしたら、"title can't be blank"などのメッセージが出ることを期待しています。 validateに関するコードを載せていなかったので追記いたします。
guest

回答1

0

自己解決

def create
@post = Item.create(item_params)
if @post.save
redirect_to root_path
else
@item = Item.new(item_params)
render :new
end
end

のelseの下に、新たにitem.newをしてしまっているので、itemを取得し直してしまい、エラーが出ていないまっさらnewのビューが出てきてしまっていました。
また、@post = Item.create(item_params)は@post = Item.new(item_params)の間違いでした。
createメソッドがnewとsaveを組み合わせたものという認識がありませんでした。
最終的には
@item = Item.new(item_params)
if @item.save
redirect_to root_path
else
render :new
end

というコードで想定した動きになりました。

投稿のような機能だったのでわざわざ@postと設定しましたが、他のアクションでは@itemとしているのでわかりやすさのために揃えました。

投稿2022/07/01 08:07

DRUSS

総合スコア10

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問