label
label(object_name, method, content_or_options = nil, options = nil, &block)
public
Returns a label tag tailored for labelling an input field for a specified attribute (identified by method) on an object assigned to the template (identified by object). The text of label will default to the attribute name unless a translation is found in the current I18n locale (through helpers.label.<modelname>.<attribute>) or you specify it explicitly. Additional options on the label tag can be passed as a hash with options. These options will be tagged onto the HTML as an HTML element attribute as in the example shown, except for the :value option, which is designed to target labels for radio_button tags (where the value is used in the ID of the input tag).
Examples
label(:post, :title) # => <label for="post_title">Title</label>
You can localize your labels based on model and attribute names. For example you can define the following in your locale (e.g. en.yml)
helpers: label: post: body: "Write your entire text here"
Which then will result in
label(:post, :body) # => <label for="post_body">Write your entire text here</label>
Localization can also be based purely on the translation of the attribute-name (if you are using ActiveRecord):
activerecord: attributes: post: cost: "Total cost" label(:post, :cost) # => <label for="post_cost">Total cost</label> label(:post, :title, "A short title") # => <label for="post_title">A short title</label> label(:post, :title, "A short title", class: "title_label") # => <label for="post_title" class="title_label">A short title</label> label(:post, :privacy, "Public Post", value: "public") # => <label for="post_privacy_public">Public Post</label> label(:post, :terms) do raw('Accept <a href="/terms">Terms</a>.') end # => <label for="post_terms">Accept <a href="/terms">Terms</a>.</label>
Translations of label method
The label method won’t use your translated attribute names - which seems like big disadvantage of this method.
For a quick workaround, try using this in a helper:
def label(object_name, method, text = nil, options = {}) text ||= object_name.classify.constantize.human_attribute_name(method.to_s) ActionView::Helpers::InstanceTag.new(object_name, method, self, options.delete(:object)).to_label_tag(text, options) end
I didn’t properly test this, but it seems to work.
label DOES translate
Maybe it used to not translate but I know it does as of 2.3.8. It is first lookup on the key:
helpers.label.<object_name>.<method_name>
If that doesn’t return anything it will use the human_attribute_name method on ActiveRecord::Base to translated which uses:
activerecord.attributes.<object>.<attribute>
I generally use both of these keys even when I don’t want to translate but just to have a single place where all my adjusted labels are stored.
If any form will need to use the same adjustment given the same object and attribute then I put in on the activerecord key. If the adjustment is form specific then I put it on the helpers key. Here is an example from real working code:
en: activerecord: attributes: "content/rich_text": name: Page name helpers: label: content_rich_text: testimonial_enabled: Enabled
Note that my AR object is a namespaced object (Content::RichText). In the activerecord key I need to change this to content/rich_text so if can find the correct key and put it in quotes to make it valid YAML. At the helper level on the other hand the namespace simply becomes an _.
Mistake in example for Rails 3
This code doesn’t work:
activemodel: attribute: post: cost: "Total cost"
Everything is OK with this one:
activerecord: attributes: post: cost: "Total cost"
Unusual block calling
It is important to note that the block form of this method is unlike any other block form in Rails. You would expect this to work:
<%= f.label :terms_and_conditions do %> Accept <%= link_to_page 'Terms and Conditions' %> <% end %>
But doing this ends up messing up the form (I ended up with the form repeating itself). Instead you need to do:
<%= f.label :terms_and_conditions do 'Accept ' + link_to_page('Terms and Conditions') end %>
Which is really only mildly better than not using the block form:
<%= f.label :terms_and_conditions, 'Accept ' + link_to_page('Terms and Conditions') %>
You are actually better of using capture if your code lends itself to the first non-working form:
<%= f.label :terms_and_conditions, (capture do %> Accept <%= link_to_page 'Terms and Conditions' %> <% end) %>
Or if you prefer brackets to parenthesis you can do:
<%= f.label :terms_and_conditions, capture { %> Accept <%= link_to_page 'Terms and Conditions' %> <% } %>
Save yourself a little typing
We often have a form with a select box that selects a model association. So for example to select a colour, when there is an associated Colour model, a select box will typically select :colour_id.
In this case, ActionView automatically humanizes :colour_id to produce “Colour” as the label text.
customizing text when using label in a form
Instead of the default text Email you can change it to “Primary Email” like this: f.label :email, “Primary Email”