LoginSignup
19
23

More than 3 years have passed since last update.

各formごとにvalidationのエラーメッセージ出したい

Last updated at Posted at 2016-05-02

validateしたエラーメッセージの表示について

もっと簡単なやり方教えていただきたいのでqiitaにmemoとしてアップしました。

こういうのはよく見る

hogehoge.html.haml
= form_for @hogehoge do |f|
    - if @hogehoge.errors.any?
        %ul
          - @hogehoge.errors.full_messages.each do |msg|
            %li= msg

こういう風にまとめてメッセージを表示される

スクリーンショット 2016-05-02 15.28.49.png

でも、↓みたいに表示したい
スクリーンショット 2016-05-02 15.28.56.png

こういうのはよくある話だと思ってgemとかプラグインで解決できるだろうと思ってぐぐってみてもなかなかいい情報が見つからず困る。

1つ目の解決策

@xxxx.errors.messagesから取り出す
@xxxx.errors.messages[:zipcode][0]にエラーメッセージ入るのでこれを表示

 .field
  = f.label :zipcode
  = f.text_field :zipcode
  %p{class: 'error'}=@xxxx.errors.messages[:zipcode][0]

デメリット

  • これだと項目数多いと途端につらい。
  • Modelに presence: {message: 'XXXXは必須入力です'} 等を書く必要がある
  • なによりとてもイケてない感に襲われる

2つ目の解決策

formBuilderをつくってみる

参考:http://mmmpa.hatenablog.com/entry/2015/01/12/Rails_%E3%81%AE_form_for_%E3%81%A7%E3%82%A8%E3%83%A9%E3%83%BC%E5%87%BA%E3%81%9F%E3%81%A8%E3%81%8D%E3%81%AB%E3%80%81%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%AF%E3%81%A1%E3%82%83%E3%82%93%E3%81%A8%E3%82%A8

まんま使ってみる

builders/with_error_form_builder.rb
class WithErrorFormBuilder < ActionView::Helpers::FormBuilder
  def pick_errors(attribute)
    return nil if @object.nil? || (messages = @object.errors.messages[attribute]).nil?
    lis = messages.collect do |message|
      %{<li>#{message}</li>}
    end.join

    %{<ul class="errors">#{lis}</ul>}.html_safe
  end

  def text_field(attribute, options={})
    return super if options[:no_errors]

    super + pick_errors(attribute)
  end
end

こうなった。項目名を出したい・・・。

スクリーンショット 2016-05-02 15.46.44.png

@hogehoge.errors.full_messages では項目名+エラー内容となっているので
これを生成しているメソッドを探す

~/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/activemodel-4.2.6/lib/active_model/errors.rb
# Returns a full message for a given attribute.
#
#   person.errors.full_message(:name, 'is invalid') # => "Name is invalid"
def full_message(attribute, message)
  return message if attribute == :base
  attr_name = attribute.to_s.tr('.', '_').humanize
  attr_name = @base.class.human_attribute_name(attribute, default: attr_name)
  I18n.t(:"errors.format", {
    default:  "%{attribute} %{message}",
    attribute: attr_name,
    message:   message
  })
end

full_messageをつかってメッセージを組み立てることで出来た。

builders/with_errror_form_builder.rb
class WithErrorFormBuilder < ActionView::Helpers::FormBuilder

  def pick_errors(attribute)
    return nil if @object.nil? || (messages = @object.errors.messages[attribute]).nil?
    lis = messages.collect do |message|
      %{<li>#{@object.errors.full_message(attribute, message)}</li>}
    end.join

    %{<ul class="errors">#{lis}</ul>}.html_safe
  end

  def text_field(attribute, options={})
    return super if options[:no_errors]

    super + pick_errors(attribute)
  end
end
19
23
1

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
19
23