Help us understand the problem. What is going on with this article?

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

More than 3 years have passed since last update.

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_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>#{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
Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away