When I was working on the Validations patch a few days ago I noticed
that having human_attribute_name uppercasing the attribute name might
not be a good idea at all. Consider something like this:
full_message_format = "This {{model}}'s {{attribute}} {{message}}."
Validations traditionally use human_name for the model class name and
human_attribute_name for the attribute name. Both internally use
Inflections#humanize which capitalizes the first word of the given
string.
So, we'd get a result like "This Squirrel's Nose is broken." ... wtf.
Obviously this is broken even for English.
Where does the assumption come from that "humanizing" a String
involves "capitalizing its first word"?
I could understand if something like #sentencize would do that, but
the humanized result of "squirrel_id" would be just "squirrel", no?
Any opinions?
[1] https://rails.lighthouseapp.com/projects/8994/tickets/745-form-label-should-use-i18n
Perfect!
Can we have that tattoo'ed on every Rails dev's forehead? ;) Ok, at
least I'll copy and keep it for some kind of best-practice quotes
collection. Thanks :)
> > Maybe a configuration value that lowercase the attribute? Or a
> > {{downcased_attribute}} interpolation value?
> >>
> >> full_message_format = "This {{model}}'s {{attribute}} {{message}}."
> >>
>
> How about:
>
> full_message_format = "This %{model}'s %{attribute} %{message}."
>
> vs
>
> full_message_format = "%{Model} %{attribute} hat %{message}."
>
> I.e., the case of the interpolation variable is used as an
> indication of whether or not to capitalize.
Wicked. We'd then need to pass both :Model and :model as well
as :Attribute and :attribute, right?
I've been thinking about something like "%{model:humanize} %
{attribute} hat %{message}." ... but maybe this is going a bit over
board.
>
> On 27.08.2009, at 07:20, Lawrence Pit wrote:
>> I think the rule is: human_attribute_name, human_name and humanize
>> should not be used anywhere in rails internals, specifically not by
>> AR validation methods, except to serve as a default value. Method
>> humanize should be considered a helper method for the English
>> language only.
>
> Perfect!
>
> Can we have that tattoo'ed on every Rails dev's forehead? ;) Ok, at
> least I'll copy and keep it for some kind of best-practice quotes
> collection. Thanks :)
While I do agree with this on one hard, on the other, wouldn't it make
sense to be able configure inflections per locale?
>
>>> Maybe a configuration value that lowercase the attribute? Or a
>>> {{downcased_attribute}} interpolation value?
>>>>
>>>> full_message_format = "This {{model}}'s {{attribute}} {{message}}."
>>>>
>>
>> How about:
>>
>> full_message_format = "This %{model}'s %{attribute} %{message}."
>>
>> vs
>>
>> full_message_format = "%{Model} %{attribute} hat %{message}."
>>
>> I.e., the case of the interpolation variable is used as an
>> indication of whether or not to capitalize.
>
> Wicked. We'd then need to pass both :Model and :model as well
> as :Attribute and :attribute, right?
>
> I've been thinking about something like "%{model:humanize} %
> {attribute} hat %{message}." ... but maybe this is going a bit over
> board.
That's quite similar to liquid[1], and starts approaching a full on
templating engine. I'm not necessarily opposed to that idea, but I'm
not sure it's the best approach to the problem. capitalizing the
interpolation key is definitely clever, but may be confusing/
Although it would be more verbose, providing a hierarchy of
full_message translations would be a foolproof way of dealing with
this issue, and I think that should be encouraged over trying to make
the code too clever.
Yeah, I actually agree with this. :-)
Cheers,
Lawrence
>
> Inflection per locale is a good suggestion, but it does not solve the
> problem. I might have the label "Name" (upcased) but in my error
> message it should be "User's name is invalid" (downcased).
This is exactly where being able to specify a full message for each
error would come in handy. IMO, the main purpose of the generic
full_message_format was to provide a quick and easy way to remove the
attribute name concatenation while preserving backwards compatibility.
IMO inflection per locale is something that would be for app
developers, not necessarily for use by the internals
>
> Another suggestion would be a label lookup:
>
> views:
> labels:
> user:
> name: "Your name:"
>
> Where human_attribute_name would be a fallback if it's not found in
> labels. This way would at least decouple actionview and activerecord
> (i.e. it would work with datamapper and other non object forms). If we
> do that, we should also consider to add lazy defaults:
>
> I18n.t("views.labels.#{model.class.name}.#{attribute}") do
> model.class.human_attribute_name(attribute)
> end
>
> We would call "model.class.human_attribute_name" just if
> "views.labels.model.attribute" can't be found. A straightforward gain
> if we compare it with:
>
> I18n.t("views.labels.#{model.class.name}.#{attribute}", :default =>
> model.class.human_attribute_name(attribute))
>
Agreed. In fact, I'd suggest that every single part of rails that
currently uses inflections should do so only as a fallback, after
having called I18n lookup first.
> Wdyt?
>
> Regards!