🧦
バリデーションは効いているのにエラーメッセージが出ないときの対処法
この記事で分かること
- エラーメッセージが出ない原因のパターン
→ (status: :unprocessable_entity)を追加
→ formで(local: true)を追加
→ createアクションの見直し
完成イメージ
-
Before
-
After
解決した添削コード
items_controller
class Public::ItemsController < ApplicationController
def create
@item = Item.new(item_params)
@item.user_id = current_user.id
if @item.save
flash[:notice] = "投稿に成功しました"
redirect_to item_path(@item)
else
@items = Item.order("created_at DESC").page(params[:page])
- @item = Item.new
@user = current_user
@genres = Genre.all
@products = Product.where(is_secret: true)
flash[:alert] = "投稿に失敗しました"
render 'index'
end
end
def index
@products = Product.where(is_secret: true)
@items = Item.order("created_at DESC").page(params[:page])
@user = current_user
@item = Item.new
@genres = Genre.all
if params[:latest]
@items = Item.latest.page(params[:page])
elsif params[:most_commented]
@items = Item.most_commented
@items = Kaminari.paginate_array(@items).page(params[:page])
elsif params[:most_favorited]
@items = Item.most_favorited
@items = Kaminari.paginate_array(@items).page(params[:page])
else
@items = Item.order("created_at DESC").page(params[:page])
end
end
end
解決策を3つ紹介
私が実践した解決策は以下の3点です。
- renderに(status: :unprocessable_entity)を追加
- formで(local: true)の記述を確認
- createアクションの見直し
私は「createアクションの見直し」で解決しました。
1.renderに(status: :unprocessable_entity)を追加
items_controller
else
@items = Item.order("created_at DESC").page(params[:page])
@user = current_user
@genres = Genre.all
@products = Product.where(is_secret: true)
flash[:alert] = "投稿に失敗しました"
+ render 'index', status: :unprocessable_entity
end
end
Railsのバージョンによっては、エラーメッセージを出力するには上記の記述を追加する必要があるらしいです。私は記述してみましたが変化はありませんでした。
2.formで(local: true)の記述を確認
items/_form
<%= form_with model: item, local: true do |f| %>
formに(local: true)を記述していない場合も、エラー文が出ない原因になるそうです。
理由として、記述していないデフォルト状態では、(remote: true)になっているからです。
今回は、Ajax処理は必要がないので、local: tureと記述されているか確認します。
3.createアクションの見直し
items_controller
class Public::ItemsController < ApplicationController
def create
@item = Item.new(item_params)
@item.user_id = current_user.id
if @item.save
flash[:notice] = "投稿に成功しました"
redirect_to item_path(@item)
else
@items = Item.order("created_at DESC").page(params[:page])
- @item = Item.new
@user = current_user
@genres = Genre.all
@products = Product.where(is_secret: true)
flash[:alert] = "投稿に失敗しました"
render 'index'
end
end
(render)の記述を確認したときに、@Item.newとして再定義していることに気づきました。
新しく定義するとバリデーションしていない(まだ投稿していない)Itemを参照することになり、エラー文が出てこないみたいでした。
感想
エラー文の設定の見積もりを30分ぐらいで考えていましたが、ここまでで1時間ぐらいかかってしまいました。日本語化も少し苦戦したので、また記事にしようと思います。
この記事をかいた人
23/6/1にDWCに入学し、主にRailsの学習に取り組みました。卒業が近づきこれから何で学習をするか悩んだときに、技術ブログをしようと考えました。初心者ですがよろしくお願いします。
Discussion