Discussion Forums
- Topic List
- Most Recent Posts
- Sign In for more options
I needed to fix the default error_messages mechanism which was bad in one particular instance, which lead to "Secret answers answer can't be blank". However, I did not want to reinvent or have to provide error messages for every validate, which were some of the solutions I found around the net. I started with an idea I read about overriding error_messages_for, which is what I did. I left it largely intact because I did not want to mess with the default behavior.
You should be able to paste this function into any of your module helpers and anywhere you use
it should work exactly as it did before. Now for the changes...
The header_message can be changed but I did not want to lose the count so you can provide any string you want and use the $COUNT place holder. This is not case sensitive.
"my form had $COUNT errors" %>
That is helpful but now for the major fix. If you prepend the :message text with an ! (exclamation point) it will take that string literally. If you do not prepend it with an ! it works as it always did.
validates_presence_of :answer, :message => '!Answers must be provided for each security question'
Still want to use the attribute name but not at the beginning of the string, then use the $attr place holder.
validates_presence_of :answer, :message => '!There were problems with $attr, so fix it!'
The code to paste...
def error_messages_for(*params)
options = params.extract_options!.symbolize_keys
if object = options.delete(:object)
objects = [object].flatten
else
objects = params.collect {|object_name| instance_variable_get("@#{object_name}") }.compact
end
count = objects.inject(0) {|sum, object| sum + object.errors.count }
unless count.zero?
html = {}
[:id, :class].each do |key|
if options.include?(key)
value = options[key]
html[key] = value unless value.blank?
else
html[key] = 'errorExplanation'
end
end
options[:object_name] ||= params.first
I18n.with_options :locale => options[:locale], :scope => [:activerecord, :errors, :template] do |locale|
header_message = if options.include?(:header_message)
options[:header_message].gsub(/\$COUNT/i, count.to_s)
else
object_name = options[:object_name].to_s.gsub('_', ' ')
object_name = I18n.t(object_name, :default => object_name, :scope => [:activerecord, :models], :count => 1)
locale.t :header, :count => count, :model => object_name
end
message = options.include?(:message) ? options[:message] : locale.t(:body)
error_messages = objects.map do |obj|
obj.errors.collect do |attr, msg|
if msg.starts_with?('!')
msg[0] = ''
fmt_msg = msg.gsub(/\$ATTR/i, attr.humanize.downcase)
else
fmt_msg = [attr.humanize, msg].join(' ')
end
content_tag( :li, fmt_msg )
end
end
contents = ''
contents << content_tag(options[:header_tag] || :h2, header_message) unless header_message.blank?
contents << content_tag(:p, message) unless message.blank?
contents << content_tag(:ul, error_messages)
content_tag(:div, contents, html)
end
else
''
end
end
