82
67

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[Rails] field_error_proc を使ってバリデーションエラーの表示をいい感じにする

Last updated at Posted at 2015-11-01

背景

  • Rails では、バリデーションエラーのあった項目はデフォルトで <div class="field_with_errors"> で囲まれる
  • この挙動は、 config/application.rbconfig.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

こんなかんじで表示されるようになります:

Kobito.72t7QU.png

解説

  • instanceActionView::Helpers::Tags::Base のサブクラスになるっぽい
  • instance のクラスを調べることによって、ラベルの場合には何もせずそのまま返す
  • instance.error_message にバリデーションの内容が入っているので、取り出す

参考文献

82
67
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
82
67

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?