Table of Contents
- 1. form_for
- 2. Parsing form data
- 2.1. Simple query strings
- 2.2. Nesting
- 2.3. Multiple records
- 3. Example
- 3.1. Controller
- 3.2. View
- 3.3. HTML
- 3.4. params
- 4. fields_for
- 5. RESTful form_for
- 6. Input field helpers
- 7. Multipart form
1. form_for
form_for is used to easily manipulate HTML forms which are based upon ActiveRecord model objects:
<%= form_for(:customer, @customer, :url => { :controller => "customers", :action => "create" }, :html => { :multipart => true, :method => :put }) do |f| %>
<%= f.text_field :age %>
<%= text_field "customer", :age %>
<%= submit_tag %>
<% end %>
Table 1.1 form_for Parameters
| Key | Value | Purpose |
|---|---|---|
:customer required | :symbol or "string" | The name of the ActiveRecord model object for all the fields in the form. All input fields will be prefixed with this. Rails will also look for an @instance_variable with the same name which should contain an instance of an existing or new ActiveRecord model object |
@customer optional | Object | If the @instance_variable containing the ActiveRecord model object is named differently, you can pass a variable containing the actual model object here |
:url optional | "string" or {hash} | The URL to post the form to. Can take an explicit url as a string, or a hash in the same format as url_for |
:html optional | {hash} | A {hash} of HTML attributes which will be added to the HTML <form> tag. |
:method optional | :symbol | Pass as part of the {hash} of HTML attributes. Can be :put, :post, :get or :delete |
2. Parsing form data
When a form is submitted to a Rails application, the parameters are automatically translated by Rails into the params object which is accessible as a hash structure.
2.1. Simple query strings
Key/value pairs of your form’s input fields are stored simply as key/value pairs in the params hash, such as the id which is extracted by routing from the URL:
| URL | Parameters | Hash constructed |
|---|---|---|
/customers/1 | id=1 | { :id => "1" } |
/customers/1?color=red | id=1&color=red | { :id => "1", :color => "red" } |
2.2. Nesting
Square brackets [] are used to build more complex, nested structures:
| Field helper | Parameters | Hash constructed |
|---|---|---|
text_field :user, :name | user[name]=David | { :user => { :name => "David" } |
text_field "user[address]", :city | user[address][city]=London | { :user => { :address => { :city => "London" }}} |
text_field "user[address]", :street | user[address][street]=Road | { :user => { :address => { :street => "Road" }}} |
2.3. Multiple records
Using empty square brackets [] after the name of a model object, such as address[], will insert the id of the record you are editing into the input field, useful for editing multiple records on one form:
| Field helper | Parameters | Hash constructed |
|---|---|---|
text_field "address[]", :country | address[4][country]=England | { :address => { 4 => { :country => "England" }}} |
text_field "address[]", :town | address[4][town]=London | { :address => { 4 => { :town => "London" }}} |
If the record is new and has no id, then upon submitting the form, Rails will convert the fields into an array of hashes in order of appearance.
text_field "address[]", :country
text_field "address[]", :town
text_field "address[]", :country
text_field "address[]", :town
{ :address => [
{ :country => "England", :town => "London" },
{ :country => "Australia", :town => "Sydney" }
]
}
3. Example
3.1. Controller
def new
@customer = Customer.new
3.times do
@customer.addresses.build
end
end
3.2. View
<% form_for(@customer) do |f| %>
<%= f.text_field :name %>
<%= f.text_field :email %>
<% @customer.addresses.each do |address| %>
<% fields_for "customer[addresses][]", address do |fields| %>
<%= fields.text_field :number %>
<%= fields.text_field :street %>
<% end %>
<% end %>
3.3. HTML
<form id="new_customer" class="new_customer" method="post" action="/customers">
<input type="text" size="30" name="customer[name]"/>
<input type="text" size="30" name="customer[email]"/>
<input type="text" size="30" name="customer[addresses][][number]"/>
<input type="text" size="30" name="customer[addresses][][street]"/>
<input type="text" size="30" name="customer[addresses][][number]"/>
<input type="text" size="30" name="customer[addresses][][street]"/>
<input type="text" size="30" name="customer[addresses][][number]"/>
<input type="text" size="30" name="customer[addresses][][street]"/>
<input type="submit" value="Create" name="commit"/>
</form>
3.4. params
params = {
"customer" => { "name"=>"David Pettifer",
"email"=>"david.p@dizzy.co.uk",
"addresses"=> [
{ "number"=>"31", "street"=>"High" },
{ "number"=>"22", "street"=>"Brook" },
{ "number"=>"16", "street"=>"Kents" } ]
} }
4. fields_for
fields_for creates a scope around a specific model object like form_for, but doesn’t create the form tags themselves, making fields_for suitable for specifying additional model objects in the same form. See the example.
5. RESTful form_for
When standard routes are used in a RESTful context, Rails will reflect upon the object passed to it and automatically build a form with the relevant RESTful URL depending on whether the form is wrapping a new record (create) or an existing record (update). Nested routes will require you to be more verbose. Standard routes
| Standard routes | new record? | method | URL |
|---|---|---|---|
form_for(@customer) | yes | POST | /customers |
form_for(@customer) | no | PUT | /customers/1 |
| Nested routes | new record? | method | URL |
|---|---|---|---|
form_for(@address, :url => customer_addresses_path(@customer)) | yes | POST | /customers/1/addresses |
form_for(@address, :url => customer_addresses_path(@customer)) | no | PUT | /customers/1/addresses/24 |
6. Input field helpers
f.error_messages_for
f.check_box :terms, { :class => 'check' }, "yes", "no"
f.file_field :image
f.hidden_field :id
f.label :customer, "Text for label"
f.password_field :password
f.radio_button :language, "French"
f.text_area :comment, :size => "20x30", :disabled => "disabled"
f.text_field :age, :size => "20", :class => "age_box"
7. Multipart form
7.1. View
<% form_for(@customer, :html => { :multipart => true }) do |f| %>
<%= f.file_field :image_file %>
<%= submit_tag %>
<% end %>
7.2. Model
class Customer < ActiveRecord::Base
def image_file=(uploaded_data)
self.filename = uploaded_data.original_filename
self.image_data = uploaded_data.read
self.size = uploaded_data.size
self.content_type = uploaded_data.content_type
end
end

Cheatsheets





11 MONTHS AGO
vinay
Thanks
thanks for this nice article....
9 MONTHS AGO
mosquete
Visual representation not necessary
Thanks for the cheatsheet! And here's some feedback: I think the "Visual representation of params" is unnecessary. The description of "params[]" just above it leaves no doubt about the organization of its content. So that space could be used for something else.
4 MONTHS AGO
Ganesh
Thanks
Thanks lot for the gr8 article
2 MONTHS AGO
Jerry
Thanks
Phenomenal. This article helped me understand form helpers better.
2 MONTHS AGO
Praveen
Great!
Great article. Thanks for the help.
ABOUT 1 MONTH AGO
Wim
Question
Hi Mr. Dizzy, I was wondering if you could help me with a related problem. My form, when using drop down menus, posts the following : aspectvalues[id] 11 aspectvalues[id] 15 How can i read these numbers from my controller pls? Thank you, Wim
17 MINUTES AGO
Somnath Pawar
Excellent
This is excellent information for ruby on rails users.
7 MINUTES AGO
Somnath Pawar
Excellent
This is really excellent information for rails users.