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
こういう風にまとめてメッセージを表示される
こういうのはよくある話だと思って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をつくってみる
まんま使ってみる
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
こうなった。項目名を出したい・・・。
@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