Clarify fields_for and form builders

This commit is contained in:
Frederick Cheung
2009-01-01 10:32:22 +00:00
parent d9e6413492
commit 32fee815fa

View File

@@ -582,9 +582,9 @@ File upload form
:multipart - If set to true, the enctype is set to "multipart/form-data".
Scoping out form controls with `fields_for`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-------------------------------------------
`fields_for` creates a form builder in exactly the same way as `form_for` but doesn't create the actual `<form>` tags. In that sense it creates a scope around a specific model object like `form_for`, which is useful for specifying additional model objects in the same form. For example we might a Person model with an associated ContactDetail model. We could create a form for editing both like so:
`fields_for` creates a form builder in exactly the same way as `form_for` but doesn't create the actual `<form>` tags. It creates a scope around a specific model object like `form_for`, which is useful for specifying additional model objects in the same form. For example if you had a Person model with an associated ContactDetail model you could create a form for editing both like so:
-------------
<% form_for @person do |person_form| %>
<%= person_form.text_field :name %>
@@ -593,26 +593,47 @@ Scoping out form controls with `fields_for`
<% end %>
<% end %>
-------------
which produces the following output:
-------------
<form action="/people/1" class="edit_person" id="edit_person_1" method="post">
<input id="person_name" name="person[name]" size="30" type="text" />
<input id="contact_detail_phone_number" name="contact_detail[phone_number]" size="30" type="text" />
</form>
-------------
Making custom form builders
~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can also build forms using a customized FormBuilder class. Subclass FormBuilder and override or define some more helpers, then use your custom builder. For example, lets say you made a helper to automatically add labels to form inputs.
Form builders
-------------
----------------------------------------------------------------------------
<% 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? %>
As mentioned previously the object yielded by `form_for` and `fields_for` is an instance of FormBuilder (or a subclass thereof). Form builders encapsulate the notion of displaying a form elements for a single object. While you can of course write helpers for your forms in the usual way you can also subclass FormBuilder and add the helpers there. For example
----------
<% form_for @person do |f| %>
<%= text_field_with_label f, :first_name %>
<% end %>
----------------------------------------------------------------------------
----------
can be replaced with
----------
<% form_for @person, :builder => LabellingFormBuilder do |f| %>
<%= f.text_field :first_name %>
<% end %>
----------
by defining a LabellingFormBuilder class similar to the following:
-------
class LabellingFormBuilder < FormBuilder
def text_field attribute, options={}
label(attribute) + text_field(attribute, options)
end
end
-------
If you reuse this frequently you could define a `labeled_form_for` helper that automatically applies the `:builder => LabellingFormBuilder` option.
The form builder used also determines what happens when you do
------
<%= render :partial => f %>
------
If `f` is an instance of FormBuilder then this will render the 'form' partial, setting the partial's object to the form builder. If the form builder is of class LabellingFormBuilder then the 'labelling_form' partial would be rendered instead.
* `form_for` within a namespace
@@ -630,8 +651,6 @@ time_zone_options_for_select(selected = nil, priority_zones = nil, model = ::Act
time_zone_select(object, method, priority_zones = nil, options = {}, html_options = {})
----------------------------------------------------------------------------
Form builders
-------------
== Changelog ==