8th
On Providing Alternate Labels to ActiveRecord Attributes
I cooked up a simple enhancement to ActiveRecord::Errors#full_messages to allow me to pass a mapping of attribute to label. Here’s the snippet:
module ActiveRecord
class Errors
def full_messages_with_attr_mapping(mappings)
mappings.symbolize_keys!
full_messages = []
@errors.each_key do |attr|
@errors[attr].each do |msg|
next if msg.nil?
if attr == "base"
full_messages << msg
else
full_messages << (mappings[attr.to_sym] || @base.class.human_attribute_name(attr)) + " " + msg
end
end
end
full_messages
end
end
end
Let me walk through the scenario where I found this snippet useful.
Suppose I had a User model with the field ic to store the Malaysian National Registration Identification Card number. If I hit validation errors, I’ll get an ugly error message when I use @user.errors.full_messages.each { ... }
Ic is not valid.
With the snippet above, I’ll call it with @user.errors.full_messages_with_attr_mapping(:ic => 'I/C Number').each { ... } and get
I/C Number is not valid.
Much nicer.
However, I don’t like this solution much because I can’t alias_method_chain this to full_messages (because of the explicit mapping params). The downside of this is @user.errors.each_full { ... } will not do what I want as it uses full_messages.
Ideally, I want something that looks like:
class User < ActiveRecord::Base
attr_label :ic => 'I/C Number', :hp => 'H/P Number'
validates_mykad_of :ic
...
end
or, we can add a new key to specify the preferred label, much like how validates_* lets you override the error message.
class User < ActiveRecord::Base
validates_mykad_of :ic, :message => 'is not valid', :label => 'I/C Number'
...
end
Or something like that.
I prefer Option 1 as it opens up more than just validation error messages. Other places it’ll be useful is in forms
<% form_for :user do |f| %>
<%= f.label :ic %>
<% end %>
Is there a better way? Are there plugins that allow one to do this already?
