@@ -16,17 +16,28 @@ module Helpers
1616 # Form helpers are designed to make working with resources much easier
1717 # compared to using vanilla HTML.
1818 #
19- # Forms for models are created with +form_for+. That method yields a form
20- # builder that knows the model the form is about. The form builder is thus
21- # able to generate default values for input fields that correspond to model
22- # attributes, and also convenient names, IDs, endpoints, etc.
19+ # Typically, a form designed to create or update a resource reflects the
20+ # identity of the resource in several ways: (i) the url that the form is
21+ # sent to (the form element's +action+ attribute) should result in a request
22+ # being routed to the appropriate controller action (with the appropriate <tt>:id</tt>
23+ # parameter in the case of an existing resource), (ii) input fields should
24+ # be named in such a way that in the controller their values appear in the
25+ # appropriate places within the +params+ hash, and (iii) for an existing record,
26+ # when the form is initially displayed, input fields corresponding to attributes
27+ # of the resource should show the current values of those attributes.
2328 #
24- # Conventions in the generated field names allow controllers to receive form
25- # data nicely structured in +params+ with no effort on your side.
29+ # In Rails, this is usually achieved by creating the form using +form_for+ and
30+ # a number of related helper methods. +form_for+ generates an appropriate <tt>form</tt>
31+ # tag and yields a form builder object that knows the model the form is about.
32+ # Input fields are created by calling methods defined on the form builder, which
33+ # means they are able to generate the appropriate names and default values
34+ # corresponding to the model attributes, as well as convenient IDs, etc.
35+ # Conventions in the generated field names allow controllers to receive form data
36+ # nicely structured in +params+ with no effort on your side.
2637 #
2738 # For example, to create a new person you typically set up a new instance of
2839 # +Person+ in the <tt>PeopleController#new</tt> action, <tt>@person</tt>, and
29- # pass it to +form_for+:
40+ # in the view template pass that object to +form_for+:
3041 #
3142 # <%= form_for @person do |f| %>
3243 # <%= f.label :first_name %>:
@@ -109,29 +120,14 @@ def convert_to_model(object)
109120 object . respond_to? ( :to_model ) ? object . to_model : object
110121 end
111122
112- # Creates a form and a scope around a specific model object that is used
113- # as a base for questioning about values for the fields .
123+ # Creates a form that allows the user to create or update the attributes
124+ # of a specific model object .
114125 #
115- # Rails provides succinct resource-oriented form generation with +form_for+
116- # like this:
117- #
118- # <%= form_for @offer do |f| %>
119- # <%= f.label :version, 'Version' %>:
120- # <%= f.text_field :version %><br />
121- # <%= f.label :author, 'Author' %>:
122- # <%= f.text_field :author %><br />
123- # <%= f.submit %>
124- # <% end %>
125- #
126- # There, +form_for+ is able to generate the rest of RESTful form
127- # parameters based on introspection on the record, but to understand what
128- # it does we need to dig first into the alternative generic usage it is
129- # based upon.
130- #
131- # === Generic form_for
132- #
133- # The generic way to call +form_for+ yields a form builder around a
134- # model:
126+ # The method can be used in several slightly different ways, depending on
127+ # how much you wish to rely on Rails to infer automatically from the model
128+ # how the form should be constructed. For a generic model object, a form
129+ # can be created by passing +form_for+ a string or symbol representing
130+ # the object we are concerned with:
135131 #
136132 # <%= form_for :person do |f| %>
137133 # First name: <%= f.text_field :first_name %><br />
@@ -141,24 +137,39 @@ def convert_to_model(object)
141137 # <%= f.submit %>
142138 # <% end %>
143139 #
144- # There, the argument is a symbol or string with the name of the
145- # object the form is about.
146- #
147- # The form builder acts as a regular form helper that somehow carries the
148- # model. Thus, the idea is that
140+ # The variable +f+ yielded to the block is a FormBuilder object that
141+ # incorporates the knowledge about the model object represented by
142+ # <tt>:person</tt> passed to +form_for+. Methods defined on the FormBuilder
143+ # are used to generate fields bound to this model. Thus, for example,
149144 #
150145 # <%= f.text_field :first_name %>
151146 #
152- # gets expanded to
147+ # will get expanded to
153148 #
154149 # <%= text_field :person, :first_name %>
150+ # which results in an html <tt><input></tt> tag whose +name+ attribute is
151+ # <tt>person[first_name]</tt>. This means that when the form is submitted,
152+ # the value entered by the user will be available in the controller as
153+ # <tt>params[:person][:first_name]</tt>.
154+ #
155+ # For fields generated in this way using the FormBuilder,
156+ # if <tt>:person</tt> also happens to be the name of an instance variable
157+ # <tt>@person</tt>, the default value of the field shown when the form is
158+ # initially displayed (e.g. in the situation where you are editing an
159+ # existing record) will be the value of the corresponding attribute of
160+ # <tt>@person</tt>.
155161 #
156162 # The rightmost argument to +form_for+ is an
157- # optional hash of options:
158- #
159- # * <tt>:url</tt> - The URL the form is submitted to. It takes the same
160- # fields you pass to +url_for+ or +link_to+. In particular you may pass
161- # here a named route directly as well. Defaults to the current action.
163+ # optional hash of options -
164+ #
165+ # * <tt>:url</tt> - The URL the form is to be submitted to. This may be
166+ # represented in the same way as values passed to +url_for+ or +link_to+.
167+ # So for example you may use a named route directly. When the model is
168+ # represented by a string or symbol, as in the example above, if the
169+ # <tt>:url</tt> option is not specified, by default the form will be
170+ # sent back to the current url (We will describe below an alternative
171+ # resource-oriented usage of +form_for+ in which the URL does not need
172+ # to be specified explicitly).
162173 # * <tt>:namespace</tt> - A namespace for your form to ensure uniqueness of
163174 # id attributes on form elements. The namespace attribute will be prefixed
164175 # with underscore on the generated HTML id.
@@ -168,7 +179,7 @@ def convert_to_model(object)
168179 # possible to use both the stand-alone FormHelper methods and methods
169180 # from FormTagHelper. For example:
170181 #
171- # <%= form_for @ person do |f| %>
182+ # <%= form_for : person do |f| %>
172183 # First name: <%= f.text_field :first_name %>
173184 # Last name : <%= f.text_field :last_name %>
174185 # Biography : <%= text_area :person, :biography %>
@@ -180,26 +191,65 @@ def convert_to_model(object)
180191 # are designed to work with an object as base, like
181192 # FormOptionHelper#collection_select and DateHelper#datetime_select.
182193 #
183- # === Resource-oriented style
194+ # === #form_for with a model object
184195 #
185- # As we said above, in addition to manually configuring the +form_for+
186- # call, you can rely on automated resource identification, which will use
187- # the conventions and named routes of that approach. This is the
188- # preferred way to use +form_for+ nowadays.
196+ # In the examples above, the object to be created or edited was
197+ # represented by a symbol passed to +form_for+, and we noted that
198+ # a string can also be used equivalently. It is also possible, however,
199+ # to pass a model object itself to +form_for+. For example, if <tt>@post</tt>
200+ # is an existing record you wish to edit, you can create the form using
201+ #
202+ # <%= form_for @post do |f| %>
203+ # ...
204+ # <% end %>
205+ #
206+ # This behaves in almost the same way as outlined previously, with a
207+ # couple of small exceptions. First, the prefix used to name the input
208+ # elements within the form (hence the key that denotes them in the +params+
209+ # hash) is actually derived from the object's _class_, e.g. <tt>params[:post]</tt>
210+ # if the object's class is +Post+. However, this can be overwritten using
211+ # the <tt>:as</tt> option, e.g. -
212+ #
213+ # <%= form_for(@person, :as => :client) do |f| %>
214+ # ...
215+ # <% end %>
189216 #
190- # For example, if <tt>@post</tt> is an existing record you want to edit
217+ # would result in <tt>params[:client]</tt>.
218+ #
219+ # Secondly, the field values shown when the form is initially displayed
220+ # are taken from the attributes of the object passed to +form_for+,
221+ # regardless of whether the object is an instance
222+ # variable. So, for example, if we had a _local_ variable +post+
223+ # representing an existing record,
224+ #
225+ # <%= form_for post do |f| %>
226+ # ...
227+ # <% end %>
228+ #
229+ # would produce a form with fields whose initial state reflect the current
230+ # values of the attributes of +post+.
231+ #
232+ # === Resource-oriented style
233+ #
234+ # In the examples just shown, although not indicated explicitly, we still
235+ # need to use the <tt>:url</tt> option in order to specify where the
236+ # form is going to be sent. However, further simplification is possible
237+ # if the record passed to +form_for+ is a _resource_, i.e. it corresponds
238+ # to a set of RESTful routes, e.g. defined using the +resources+ method
239+ # in <tt>config/routes.rb</tt>. In this case Rails will simply infer the
240+ # appropriate URL from the record itself. For example,
191241 #
192242 # <%= form_for @post do |f| %>
193243 # ...
194244 # <% end %>
195245 #
196- # is equivalent to something like:
246+ # is then equivalent to something like:
197247 #
198248 # <%= form_for @post, :as => :post, :url => post_path(@post), :method => :put, :html => { :class => "edit_post", :id => "edit_post_45" } do |f| %>
199249 # ...
200250 # <% end %>
201251 #
202- # And for new records
252+ # And for a new record
203253 #
204254 # <%= form_for(Post.new) do |f| %>
205255 # ...
@@ -211,7 +261,7 @@ def convert_to_model(object)
211261 # ...
212262 # <% end %>
213263 #
214- # You can also overwrite the individual conventions, like this :
264+ # However you can still overwrite individual conventions, such as :
215265 #
216266 # <%= form_for(@post, :url => super_posts_path) do |f| %>
217267 # ...
@@ -223,13 +273,6 @@ def convert_to_model(object)
223273 # ...
224274 # <% end %>
225275 #
226- # If you have an object that needs to be represented as a different
227- # parameter, like a Person that acts as a Client:
228- #
229- # <%= form_for(@person, :as => :client) do |f| %>
230- # ...
231- # <% end %>
232- #
233276 # For namespaced routes, like +admin_post_url+:
234277 #
235278 # <%= form_for([:admin, @post]) do |f| %>
@@ -252,9 +295,9 @@ def convert_to_model(object)
252295 #
253296 # :method => (:get|:post|:patch|:put|:delete)
254297 #
255- # in the options hash. If the verb is not GET or POST, which are natively supported by HTML forms, the
256- # form will be set to POST and a hidden input called _method will carry the intended verb for the server
257- # to interpret.
298+ # in the options hash. If the verb is not GET or POST, which are natively
299+ # supported by HTML forms, the form will be set to POST and a hidden input
300+ # called _method will carry the intended verb for the server to interpret.
258301 #
259302 # === Unobtrusive JavaScript
260303 #
@@ -402,30 +445,59 @@ def apply_form_for_options!(record, object, options) #:nodoc:
402445 #
403446 # === Generic Examples
404447 #
448+ # Although the usage and purpose of +field_for+ is similar to +form_for+'s,
449+ # its method signature is slightly different. Like +form_for+, it yields
450+ # a FormBuilder object associated with a particular model object to a block,
451+ # and within the block allows methods to be called on the builder to
452+ # generate fields associated with the model object. Fields may reflect
453+ # a model object in two ways - how they are named (hence how submitted
454+ # values appear within the +params+ hash in the controller) and what
455+ # default values are shown when the form the fields appear in is first
456+ # displayed. In order for both of these features to be specified independently,
457+ # both an object name (represented by either a symbol or string) and the
458+ # object itself can be passed to the method separately -
459+ #
405460 # <%= form_for @person do |person_form| %>
406461 # First name: <%= person_form.text_field :first_name %>
407462 # Last name : <%= person_form.text_field :last_name %>
408463 #
409- # <%= fields_for @person.permission do |permission_fields| %>
464+ # <%= fields_for :permission, @person.permission do |permission_fields| %>
410465 # Admin? : <%= permission_fields.check_box :admin %>
411466 # <% end %>
412467 #
413468 # <%= f.submit %>
414469 # <% end %>
415470 #
416- # ...or if you have an object that needs to be represented as a different
417- # parameter, like a Client that acts as a Person:
471+ # In this case, the checkbox field will be represented by an HTML +input+
472+ # tag with the +name+ attribute <tt>permission[admin]</tt>, and the submitted
473+ # value will appear in the controller as <tt>params[:permission][:admin]</tt>.
474+ # If <tt>@person.permission</tt> is an existing record with an attribute
475+ # +admin+, the initial state of the checkbox when first displayed will
476+ # reflect the value of <tt>@person.permission.admin</tt>.
477+ #
478+ # Often this can be simplified by passing just the name of the model
479+ # object to +fields_for+ -
418480 #
419- # <%= fields_for :person, @client do |permission_fields| %>
481+ # <%= fields_for :permission do |permission_fields| %>
420482 # Admin?: <%= permission_fields.check_box :admin %>
421483 # <% end %>
422484 #
423- # ...or if you don't have an object, just a name of the parameter:
485+ # ...in which case, if <tt>:permission</tt> also happens to be the name of an
486+ # instance variable <tt>@permission</tt>, the initial state of the input
487+ # field will reflect the value of that variable's attribute <tt>@permission.admin</tt>.
424488 #
425- # <%= fields_for :person do |permission_fields| %>
489+ # Alternatively, you can pass just the model object itself (if the first
490+ # argument isn't a string or symbol +fields_for+ will realize that the
491+ # name has been omitted) -
492+ #
493+ # <%= fields_for @person.permission do |permission_fields| %>
426494 # Admin?: <%= permission_fields.check_box :admin %>
427495 # <% end %>
428496 #
497+ # and +fields_for+ will derive the required name of the field from the
498+ # _class_ of the model object, e.g. if <tt>@person.permission</tt>, is
499+ # of class +Permission+, the field will still be named <tt>permission[admin]</tt>.
500+ #
429501 # Note: This also works for the methods in FormOptionHelper and
430502 # DateHelper that are designed to work with an object as base, like
431503 # FormOptionHelper#collection_select and DateHelper#datetime_select.
0 commit comments