背景
- Rails では、バリデーションエラーのあった項目はデフォルトで
<div class="field_with_errors">
で囲まれる - この挙動は、
config/application.rb
にconfig.action_view.field_error_proc
を指定することで変更できる- 意図しない
<div>
が入ることでデザインが崩れるとか、 Bootstrap を使っているときに.has-error
をつけたいとか気になったら動作を変えたくなってくる
- 意図しない
-
config.action_view.field_error_proc
と検索すると「<div class="field_with_errors">
をつけないようにする」とか「class名をfield_with_errors
から変える」ようなものばかりがヒットする。- → 実はもっといろんなことができる!
やりたいこと
ということで、バリデーションエラーがあったらテキストフィールドのすぐ下にエラーメッセージを表示するようにしてみましょう。
この例では Bootstrap を使っているので、
- フィールド全体を
.has-error
で囲む - エラーメッセージは Validation states のように
.help-block
を使って表示する
という方針で実装しました。
結果
config/application.rb
に実装するだけで期待通りに動きます:
config/application.rb
config.action_view.field_error_proc = Proc.new do |html_tag, instance|
if instance.kind_of?(ActionView::Helpers::Tags::Label)
# skip when label
html_tag.html_safe
else
"<div class=\"has-error\">#{html_tag}<span class=\"help-block\">#{instance.error_message.first}</span></div>".html_safe
end
end
View にはエラーメッセージの表示について一切実装する必要はありません:
view/hoges/new.html.haml
.form-group
= f.label :name
%span.label.label-danger 必須
= f.text_field :name, placeholder: '例:あべ しんぞう', class: 'form-control', required: true
こんなかんじで表示されるようになります:
解説
-
instance
はActionView::Helpers::Tags::Base
のサブクラスになるっぽい -
instance
のクラスを調べることによって、ラベルの場合には何もせずそのまま返す -
instance.error_message
にバリデーションの内容が入っているので、取り出す