[ruby-on-rails] Labels for radio buttons in rails form

My question is similar to this one but for a Rails app.

I have a form with some radio buttons, and would like to associate labels with them. The label form helper only takes a form field as a parameter, but in this case I have multiple radio buttons for a single form field. The only way I see to do it is to manually create a label, hard coding the ID that is auto generated for the radio button. Does anyone know of a better way to do it?

For example:

<% form_for(@message) do |f| %>
    <%= label :contactmethod %>
    <%= f.radio_button :contactmethod, 'email', :checked => true %> Email
    <%= f.radio_button :contactmethod, 'sms' %> SMS
<% end %>

This generates something like:

<label for="message_contactmethod">Contactmethod</label>
<input checked="checked" id="message_contactmethod_email" name="message[contactmethod]" value="email" type="radio"> Email
<input id="message_contactmethod_sms" name="message[contactmethod]" value="sms" type="radio"> SMS

What I want:

<input checked="checked" id="message_contactmethod_email" name="message[contactmethod]" value="email" type="radio"><label for="message_contactmethod_email">Email</label>
<input id="message_contactmethod_sms" name="message[contactmethod]" value="sms" type="radio"> <label for="message_contactmethod_sms">SMS</label>

This question is related to ruby-on-rails forms

The answer is


<% form_for(@message) do |f| %>
  <%= f.radio_button :contactmethod, 'email', :checked => true %> 
  <%= label :contactmethod_email, 'Email' %>
  <%= f.radio_button :contactmethod, 'sms' %>
  <%= label :contactmethod_sms, 'SMS' %>
<% end %>

Using true/false as the value will have the field pre-filled if the model passed to the form has this attribute already filled:

= f.radio_button(:public?, true)
= f.label(:public?, "yes", value: true)
= f.radio_button(:public?, false)
= f.label(:public?, "no", value: false)

Passing the :value option to f.label will ensure the label tag's for attribute is the same as the id of the corresponding radio_button

<% form_for(@message) do |f| %>
  <%= f.radio_button :contactmethod, 'email' %> 
  <%= f.label :contactmethod, 'Email', :value => 'email' %>
  <%= f.radio_button :contactmethod, 'sms' %>
  <%= f.label :contactmethod, 'SMS', :value => 'sms' %>
<% end %>

See ActionView::Helpers::FormHelper#label

the :value option, which is designed to target labels for radio_button tags


This an example from my project for rating using radio buttons and its labels

<div class="rating">
  <%= form.radio_button :star, '1' %>
  <%= form.label :star, '?', value: '1' %>

  <%= form.radio_button :star, '2' %>
  <%= form.label :star, '?', value: '2' %>

  <%= form.radio_button :star, '3' %>
  <%= form.label :star, '?', value: '3' %>

  <%= form.radio_button :star, '4' %>
  <%= form.label :star, '?', value: '4' %>

  <%= form.radio_button :star, '5' %>
  <%= form.label :star, '?', value: '5' %>
</div>

If you want the object_name prefixed to any ID you should call form helpers on the form object:

- form_for(@message) do |f|
  = f.label :email

This also makes sure any submitted data is stored in memory should there be any validation errors etc.

If you can't call the form helper method on the form object, for example if you're using a tag helper (radio_button_tag etc.) you can interpolate the name using:

= radio_button_tag "#{f.object_name}[email]", @message.email

In this case you'd need to specify the value manually to preserve any submissions.