Module: ActionView::Helpers::FormHelper

Defined in:
lib/action_view/helpers/form_helper.rb

Overview

Provides a set of methods for working with forms and especially forms related to objects assigned to the template. The following is an example of a complete form for a person object that works for both creates and updates built with all the form helpers. The @person object was assigned by an action on the controller:

<form action="save_person" method="post">
  Name:
  <%= text_field "person", "name", "size" => 20 %>

  Password:
  <%= password_field "person", "password", "maxsize" => 20 %>

  Single?:
  <%= check_box "person", "single" %>

  Description:
  <%= text_area "person", "description", "cols" => 20 %>

  <input type="submit" value="Save">
</form>

…is compiled to:

<form action="save_person" method="post">
  Name:
  <input type="text" id="person_name" name="person[name]"
    size="20" value="<%= @person.name %>" />

  Password:
  <input type="password" id="person_password" name="person[password]"
    size="20" maxsize="20" value="<%= @person.password %>" />

  Single?:
  <input type="checkbox" id="person_single" name="person[single]" value="1" />

  Description:
  <textarea cols="20" rows="40" id="person_description" name="person[description]">
    <%= @person.description %>
  </textarea>

  <input type="submit" value="Save">
</form>

If the object name contains square brackets the id for the object will be inserted. Example:

<%= text_field "person[]", "name" %>

…becomes:

<input type="text" id="person_<%= @person.id %>_name" name="person[<%= @person.id %>][name]" value="<%= @person.name %>" />

If the helper is being used to generate a repetitive sequence of similar form elements, for example in a partial used by render_collection_of_partials, the “index” option may come in handy. Example:

<%= text_field "person", "name", "index" => 1 %>

becomes

<input type="text" id="person_1_name" name="person[1][name]" value="<%= @person.name %>" />

There's also methods for helping to build form tags in classes/ActionView/Helpers/FormOptionsHelper.html, classes/ActionView/Helpers/DateHelper.html, and classes/ActionView/Helpers/ActiveRecordHelper.html

Instance Method Summary collapse

Instance Method Details

#check_box(object_name, method, options = {}, checked_value = "1", unchecked_value = "0") ⇒ Object

Returns a checkbox tag tailored for accessing a specified attribute (identified by method) on an object assigned to the template (identified by object). It's intended that method returns an integer and if that integer is above zero, then the checkbox is checked. Additional options on the input tag can be passed as a hash with options. The checked_value defaults to 1 while the default unchecked_value is set to 0 which is convenient for boolean values. Usually unchecked checkboxes don't post anything. We work around this problem by adding a hidden value with the same name as the checkbox.

Example (call, result). Imagine that @post.validated? returns 1:

check_box("post", "validated")
  <input type="checkbox" id="post_validate" name="post[validated]" value="1" checked="checked" />
  <input name="post[validated]" type="hidden" value="0" />

Example (call, result). Imagine that @puppy.gooddog returns no:

check_box("puppy", "gooddog", {}, "yes", "no")
  <input type="checkbox" id="puppy_gooddog" name="puppy[gooddog]" value="yes" />
  <input name="puppy[gooddog]" type="hidden" value="no" />

207
208
209
# File 'lib/action_view/helpers/form_helper.rb', line 207

def check_box(object_name, method, options = {}, checked_value = "1", unchecked_value = "0")
  InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_check_box_tag(options, checked_value, unchecked_value)
end

#fields_for(object_name, *args) {|(options[:builder] || FormBuilder).new(object_name, object, self, options, proc)| ... } ⇒ Object

Creates a scope around a specific model object like form_for, but doesn't create the form tags themselves. This makes fields_for suitable for specifying additional model objects in the same form. Example:

<% form_for :person, @person, :url => { :action => "update" } do |person_form| %>
  First name: <%= person_form.text_field :first_name %>
  Last name : <%= person_form.text_field :last_name %>

  <% fields_for :permission, @person.permission do |permission_fields| %>
    Admin?  : <%= permission_fields.check_box :admin %>
  <% end %>
<% end %>

Note: This also works for the methods in FormOptionHelper and DateHelper that are designed to work with an object as base. Like collection_select and datetime_select.

Yields:

  • ((options[:builder] || FormBuilder).new(object_name, object, self, options, proc))

Raises:

  • (ArgumentError)

145
146
147
148
149
150
# File 'lib/action_view/helpers/form_helper.rb', line 145

def fields_for(object_name, *args, &proc)
  raise ArgumentError, "Missing block" unless block_given?
  options = args.last.is_a?(Hash) ? args.pop : {}
  object  = args.first
  yield((options[:builder] || FormBuilder).new(object_name, object, self, options, proc))
end

#file_field(object_name, method, options = {}) ⇒ Object

Works just like text_field, but returns an input tag of the “file” type instead, which won't have a default value.


174
175
176
# File 'lib/action_view/helpers/form_helper.rb', line 174

def file_field(object_name, method, options = {})
  InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_input_field_tag("file", options)
end

#form_for(object_name, *args, &proc) ⇒ Object

Creates a form and a scope around a specific model object, which is then used as a base for questioning about values for the fields. Examples:

<% form_for :person, @person, :url => { :action => "update" } do |f| %>
  First name: <%= f.text_field :first_name %>
  Last name : <%= f.text_field :last_name %>
  Biography : <%= f.text_area :biography %>
  Admin?    : <%= f.check_box :admin %>
<% end %>

Worth noting is that the form_for tag is called in a ERb evaluation block, not a ERb output block. So that's <% %>, not <%= %>. Also worth noting is that the form_for yields a form_builder object, in this example as f, which emulates the API for the stand-alone FormHelper methods, but without the object name. So instead of text_field :person, :name, you get away with f.text_field :name.

That in itself is a modest increase in comfort. The big news is that form_for allows us to more easily escape the instance variable convention, so while the stand-alone approach would require text_field :person, :name, :object => person to work with local variables instead of instance ones, the form_for calls remain the same. You simply declare once with :person, person and all subsequent field calls save :person and :object => person.

Also note that form_for doesn't create an exclusive scope. It's still possible to use both the stand-alone FormHelper methods and methods from FormTagHelper. Example:

<% form_for :person, @person, :url => { :action => "update" } do |f| %>
  First name: <%= f.text_field :first_name %>
  Last name : <%= f.text_field :last_name %>
  Biography : <%= text_area :person, :biography %>
  Admin?    : <%= check_box_tag "person[admin]", @person.company.admin? %>
<% end %>

Note: This also works for the methods in FormOptionHelper and DateHelper that are designed to work with an object as base. Like collection_select and datetime_select.

Html attributes for the form tag can be given as :html => …. Example:

<% form_for :person, @person, :html => {:id => 'person_form'} do |f| %>
  ...
<% end %>

You can also build forms using a customized FormBuilder class. Subclass FormBuilder and override or define some more helpers, then use your custom builder like so:

<% form_for :person, @person, :url => { :action => "update" }, :builder => LabellingFormBuilder do |f| %>
  <%= f.text_field :first_name %>
  <%= f.text_field :last_name %>
  <%= text_area :person, :biography %>
  <%= check_box_tag "person[admin]", @person.company.admin? %>
<% end %>

In many cases you will want to wrap the above in another helper, such as:

def labelled_form_for(name, object, options, &proc)
  form_for(name, object, options.merge(:builder => LabellingFormBuiler), &proc)
end

Raises:

  • (ArgumentError)

123
124
125
126
127
128
129
# File 'lib/action_view/helpers/form_helper.rb', line 123

def form_for(object_name, *args, &proc)
  raise ArgumentError, "Missing block" unless block_given?
  options = args.last.is_a?(Hash) ? args.pop : {}
  concat(form_tag(options.delete(:url) || {}, options.delete(:html) || {}), proc.binding)
  fields_for(object_name, *(args << options), &proc)
  concat('</form>', proc.binding)
end

#hidden_field(object_name, method, options = {}) ⇒ Object

Works just like text_field, but returns an input tag of the “hidden” type instead.


169
170
171
# File 'lib/action_view/helpers/form_helper.rb', line 169

def hidden_field(object_name, method, options = {})
  InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_input_field_tag("hidden", options)
end

#password_field(object_name, method, options = {}) ⇒ Object

Works just like text_field, but returns an input tag of the “password” type instead.


164
165
166
# File 'lib/action_view/helpers/form_helper.rb', line 164

def password_field(object_name, method, options = {})
  InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_input_field_tag("password", options)
end

#radio_button(object_name, method, tag_value, options = {}) ⇒ Object

Returns a radio button tag for accessing a specified attribute (identified by method) on an object assigned to the template (identified by object). If the current value of method is tag_value the radio button will be checked. Additional options on the input tag can be passed as a hash with options. Example (call, result). Imagine that @post.category returns “rails”:

radio_button("post", "category", "rails")
radio_button("post", "category", "java")
  <input type="radio" id="post_category" name="post[category]" value="rails" checked="checked" />
  <input type="radio" id="post_category" name="post[category]" value="java" />

221
222
223
# File 'lib/action_view/helpers/form_helper.rb', line 221

def radio_button(object_name, method, tag_value, options = {})
  InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_radio_button_tag(tag_value, options)
end

#text_area(object_name, method, options = {}) ⇒ Object

Returns a textarea opening and closing tag set tailored for accessing a specified attribute (identified by method) on an object assigned to the template (identified by object). Additional options on the input tag can be passed as a hash with options.

Example (call, result):

text_area("post", "body", "cols" => 20, "rows" => 40)
  <textarea cols="20" rows="40" id="post_body" name="post[body]">
    #{@post.body}
  </textarea>

187
188
189
# File 'lib/action_view/helpers/form_helper.rb', line 187

def text_area(object_name, method, options = {})
  InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_text_area_tag(options)
end

#text_field(object_name, method, options = {}) ⇒ Object

Returns an input tag of the “text” type tailored for accessing a specified attribute (identified by method) on an object assigned to the template (identified by object). Additional options on the input tag can be passed as a hash with options.

Examples (call, result):

text_field("post", "title", "size" => 20)
  <input type="text" id="post_title" name="post[title]" size="20" value="#{@post.title}" />

159
160
161
# File 'lib/action_view/helpers/form_helper.rb', line 159

def text_field(object_name, method, options = {})
  InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_input_field_tag("text", options)
end