Rails の ActiveRecord が提供するバリデーション機能で以下のようなことをやりたい:
- 各 attribute に複数のバリデーションルールが指定されている(例:
validates :name, { presence: true, length: { maximum: 100 } }
) - 画面上で各 input の横に出すのではなく一番上にまとめてエラーメッセージを列挙したい
- 画面上でそれぞれの attribute に対して最初にひっかかった一つだけエラーメッセージを表示したい
- バリデーションルールにいちいち if で「前のエラーがなかったら」とか前後関係を指定したくない
私が知る限り、こういうことは標準ではできないように思います(Rails 4.2.3 時点)。「一個引っかかったら次以降のバリデーションはスキップする」とか宣言できると便利だと思うのですが・・。
とりあえず、ちょっと力技な感じで対応しました。まず、こういう共通メソッドを定義しておきます。
def set_one_error_for_one_attribute!(model)
model.errors.keys.each do |key|
single_error = model.errors.get(key).try(:first)
model.errors.delete(key)
model.errors[key] = single_error
end
end
で、入力エラーのパターンで render する前にこれを呼び出して model.errors を書き換えてしまうだけ。
def create
# 省略...
if @comment.save
redirect_to comments_path
else
set_one_error_for_one_attribute!(@comment)
render action: 'new'
end
end