Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Changeset 6689

Show
Ignore:
Timestamp:
05/06/07 05:23:03 (2 years ago)
Author:
marcel
Message:

Modernize documentation for form helpers. Closes #8035. [jeremymcanally]

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/actionpack/CHANGELOG

    r6681 r6689  
    11*SVN* 
     2 
     3* Modernize documentation for form helpers. [jeremymcanally] 
    24 
    35* Add brief introduction to REST to the resources documentation. [fearoffish] 
  • trunk/actionpack/lib/action_view/helpers/form_helper.rb

    r6300 r6689  
    55module ActionView 
    66  module Helpers 
    7     # Form helpers are designed to make working with models much easier than just standard html elements.  These helpers 
    8     # provide a set of methods for creating forms based on your models.  Each helper deals with a different type of data. 
    9     # Instead of creating the html elements manually, you ask the helpers to create the form element.  When the form is  
    10     # submitted i.e. when the user hits the submit button, the form elements will be bundled into the params object and 
    11     # passed back to the controller. 
    12     # 
    13     # There are two types of form helper, those that specifically work with the attributes on models, and those that don't.   
    14     # First, an example of a form generated for a login page that doesn't deal with model attributes: 
    15     # 
    16     #     <% form_tag :controller => 'sessions', :action => 'new' do -%> 
    17     #       <%= text_field_tag 'login' %> 
    18     #       <%= password_field_tag 'password' %> 
    19     #  
    20     #       <%= submit_tag 'Log in' %> 
    21     #     <% end -%> 
    22     # 
    23     # This would generate the following html: 
    24     # 
    25     #     <form action="/sessions/new" method="post"> 
    26     #       <input id="login" name="login" type="text" /> 
    27     #       <input id="password" name="password" type="password" /> 
    28     #      
    29     #       <input name="commit" type="submit" value="Log in" /> 
    30     #     </form> 
    31     # 
    32     # The params object created for this would look like: 
    33     # 
    34     #     {"commit"=>"Log in", "action"=>"create", "controller"=>"sessions", "login"=>"some_user", "password"=>"some_pass"} 
    35     # 
    36     # Note how the params are not nested when creating a form this way. 
    37     # 
    38     # An example that specifically deals with a person object: 
    39     # 
    40     #     # Note: a @person variable will have been created in the controller and populated with data  
    41     #     # e.g. @person = Person.find(1) 
    42     #     <% form_for :person, @person, :url => { :action => "update" } do |f| %> 
     7    # Form helpers are designed to make working with models much easier than just standard html elements by 
     8    # providing a set of methods for creating forms based on your models.  This helper generates the HTML for forms, 
     9    # providing a method for each sort of input (e.g., text, password, select, and so on).  When the form is  
     10    # submitted (i.e., when the user hits the submit button or <tt>form.submit</tt> is called via JavaScript), the form  
     11    # inputs will be bundled into the <tt>params</tt> object and passed back to the controller. 
     12    # 
     13    # There are two types of form helpers: those that specifically work with model attributes and those that don't.   
     14    # This helper deals with those that work with model attributes; to see an example of form helpers that don't work 
     15    # with model attributes, check the ActionView::Helpers::FormTagHelper documentation. 
     16    # 
     17    # The core method of this helper, form_for, gives you the ability to create a form for a model instance;  
     18    # for example, let's say that you have a model <tt>Person</tt> and want to create a new instance of it: 
     19    # 
     20    #     # Note: a @person variable will have been created in the controller.  
     21    #     # For example: @person = Person.new 
     22    #     <% form_for :person, @person, :url => { :action => "create" } do |f| %> 
    4323    #       <%= f.text_field :first_name %> 
    4424    #       <%= f.text_field :last_name %> 
    45     #       <%= submit_tag 'Update' %> 
     25    #       <%= submit_tag 'Create' %> 
    4626    #     <% end %> 
    4727    # 
    48     # The html generated for this would be: 
    49     # 
    50     #     <form action="/persons/update" method="post"> 
     28    # The HTML generated for this would be: 
     29    # 
     30    #     <form action="/persons/create" method="post"> 
    5131    #       <input id="person_first_name" name="person[first_name]" size="30" type="text" /> 
    5232    #       <input id="person_last_name" name="person[last_name]" size="30" type="text" /> 
    53     #       <input name="commit" type="submit" value="Update" /> 
     33    #       <input name="commit" type="submit" value="Create" /> 
    5434    #     </form> 
    5535    # 
    56     # The params object created when this form is submitted would look like: 
    57     # 
    58     #     {"action"=>"create", "controller"=>"sessions", "person"=>{"first_name"=>"William", "last_name"=>"Smith"}} 
     36    # The <tt>params</tt> object created when this form is submitted would look like: 
     37    # 
     38    #     {"action"=>"create", "controller"=>"persons", "person"=>{"first_name"=>"William", "last_name"=>"Smith"}} 
    5939    #  
    60     # The form_for method generates a form based on a method, in our example if the @person object had contained any  
    61     # values they would have been set in the form (this is how edit forms are created).  Notice how the params hash  
    62     # has a nested 'person' value, which can therefore be accessed with params[:person] in the controller
     40    # The params hash has a nested <tt>person</tt> value, which can therefore be accessed with <tt>params[:person]</tt> in the controller. 
     41    # If were editing/updating an instance (e.g., <tt>Person.find(1)</tt> rather than <tt>Person.new</tt> in the controller), the objects 
     42    # attribute values are filled into the form (e.g., the <tt>person_first_name</tt> field would have that person's first name in it)
    6343    #     
    64     # If the object name contains square brackets the id for the object will be inserted. Example: 
     44    # If the object name contains square brackets the id for the object will be inserted. For example: 
    6545    # 
    6646    #   <%= text_field "person[]", "name" %>  
    6747    #  
    68     # ...becomes: 
     48    # ...will generate the following ERb. 
    6949    # 
    7050    #   <input type="text" id="person_<%= @person.id %>_name" name="person[<%= @person.id %>][name]" value="<%= @person.name %>" /> 
    7151    # 
    7252    # If the helper is being used to generate a repetitive sequence of similar form elements, for example in a partial 
    73     # used by render_collection_of_partials, the "index" option may come in handy. Example: 
     53    # used by <tt>render_collection_of_partials</tt>, the <tt>index</tt> option may come in handy. Example: 
    7454    # 
    7555    #   <%= text_field "person", "name", "index" => 1 %> 
    7656    # 
    77     # becomes 
     57    # ...becomes... 
    7858    # 
    7959    #   <input type="text" id="person_1_name" name="person[1][name]" value="<%= @person.name %>" /> 
     
    8262    # link:classes/ActionView/Helpers/DateHelper.html, and link:classes/ActionView/Helpers/ActiveRecordHelper.html 
    8363    module FormHelper 
    84       # Creates a form and a scope around a specific model object, which is then used as a base for questioning about 
    85       # values for the fields. Examples: 
     64      # Creates a form and a scope around a specific model object that is used as a base for questioning about 
     65      # values for the fields.  
    8666      # 
    8767      #   <% form_for :person, @person, :url => { :action => "update" } do |f| %> 
     
    9373      # 
    9474      # Worth noting is that the form_for tag is called in a ERb evaluation block, not an ERb output block. So that's <tt><% %></tt>,  
    95       # not <tt><%= %></tt>. Also worth noting is that form_for yields a form_builder object, in this example as f, which emulates 
     75      # not <tt><%= %></tt>. Also worth noting is that form_for yields a <tt>form_builder</tt> object, in this example as <tt>f</tt>, which emulates 
    9676      # the API for the stand-alone FormHelper methods, but without the object name. So instead of <tt>text_field :person, :name</tt>, 
    9777      # you get away with <tt>f.text_field :name</tt>.  
    9878      # 
    99       # That in itself is a modest increase in comfort. The big news is that form_for allows us to more easily escape the instance 
    100       # variable convention, so while the stand-alone approach would require <tt>text_field :person, :name, :object => person</tt>  
     79      # Even further, the form_for method allows you to more easily escape the instance variable convention.  So while the stand-alone  
     80      # approach would require <tt>text_field :person, :name, :object => person</tt>  
    10181      # to work with local variables instead of instance ones, the form_for calls remain the same. You simply declare once with  
    10282      # <tt>:person, person</tt> and all subsequent field calls save <tt>:person</tt> and <tt>:object => person</tt>. 
    10383      # 
    10484      # Also note that form_for doesn't create an exclusive scope. It's still possible to use both the stand-alone FormHelper methods 
    105       # and methods from FormTagHelper. Example: 
     85      # and methods from FormTagHelper. For example: 
    10686      # 
    10787      #   <% form_for :person, @person, :url => { :action => "update" } do |f| %> 
     
    11393      # 
    11494      # Note: This also works for the methods in FormOptionHelper and DateHelper that are designed to work with an object as base. 
    115       # Like collection_select and datetime_select. 
    116       # 
    117       # Html attributes for the form tag can be given as :html => {...}. Example: 
     95      # Like FormOptionHelper#collection_select and DateHelper#datetime_select. 
     96      # 
     97      # HTML attributes for the form tag can be given as :html => {...}. For example: 
    11898      #      
    11999      #   <% form_for :person, @person, :html => {:id => 'person_form'} do |f| %> 
     
    121101      #   <% end %> 
    122102      # 
     103      # The above form will then have the <tt>id</tt> attribute with the value </tt>person_form</tt>, which you can then 
     104      # style with CSS or manipulate with JavaScript. 
     105      # 
    123106      # You can also build forms using a customized FormBuilder class. Subclass FormBuilder and override or define some more helpers, 
    124       # then use your custom builder like so: 
     107      # then use your custom builder.  For example, let's say you made a helper to automatically add labels to form inputs. 
    125108      #    
    126109      #   <% form_for :person, @person, :url => { :action => "update" }, :builder => LabellingFormBuilder do |f| %> 
     
    131114      #   <% end %> 
    132115      #  
    133       # In many cases you will want to wrap the above in another helper, such as
     116      # In many cases you will want to wrap the above in another helper, so you could do something like the following
    134117      # 
    135118      #   def labelled_form_for(name, object, options, &proc) 
     
    137120      #   end 
    138121      # 
     122      # If you don't need to attach a form to a model instance, then check out FormTagHelper#form_tag. 
    139123      def form_for(object_name, *args, &proc) 
    140124        raise ArgumentError, "Missing block" unless block_given? 
     
    146130 
    147131      # Creates a scope around a specific model object like form_for, but doesn't create the form tags themselves. This makes 
    148       # fields_for suitable for specifying additional model objects in the same form. Example: 
    149       # 
     132      # fields_for suitable for specifying additional model objects in the same form: 
     133      # 
     134      # ==== Examples 
    150135      #   <% form_for :person, @person, :url => { :action => "update" } do |person_form| %> 
    151136      #     First name: <%= person_form.text_field :first_name %> 
     
    157142      #   <% end %> 
    158143      # 
    159       # Note: This also works for the methods in FormOptionHelper and DateHelper that are designed to work with an object as base. 
    160       # Like collection_select and datetime_select. 
     144      # Note: This also works for the methods in FormOptionHelper and DateHelper that are designed to work with an object as base, 
     145      # like FormOptionHelper#collection_select and DateHelper#datetime_select. 
    161146      def fields_for(object_name, *args, &block) 
    162147        raise ArgumentError, "Missing block" unless block_given? 
     
    170155      # Returns an input tag of the "text" type tailored for accessing a specified attribute (identified by +method+) on an object 
    171156      # assigned to the template (identified by +object+). Additional options on the input tag can be passed as a 
     157      # hash with +options+.  These options will be tagged onto the html as an HTML element attribute as in the example 
     158      # shown. 
     159      # 
     160      # ==== Examples 
     161      #   text_field(:post, :title, :size => 20) 
     162      #   # => <input type="text" id="post_title" name="post[title]" size="20" value="#{@post.title}" /> 
     163      # 
     164      #   text_field(:post, :title, :class => "create_input") 
     165      #   # => <input type="text" id="post_title" name="post[title]" value="#{@post.title}" class="create_input" /> 
     166      # 
     167      #   text_field(:session, :user, :onchange => "if $('session[user]').value == 'admin' { alert('Your login can not be admin!'); }") 
     168      #   # => <input type="text" id="session_user" name="session[user]" value="#{@session.user}" onchange = "if $('session[user]').value == 'admin' { alert('Your login can not be admin!'); }"/> 
     169      # 
     170      #   text_field(:snippet, :code, :size => 20, :class => 'code_input') 
     171      #   # => <input type="text" id="snippet_code" name="snippet[code]" size="20" value="#{@snippet.code}" class="code_input" /> 
     172      # 
     173      def text_field(object_name, method, options = {}) 
     174        InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_input_field_tag("text", options) 
     175      end 
     176 
     177      # Returns an input tag of the "password" type tailored for accessing a specified attribute (identified by +method+) on an object 
     178      # assigned to the template (identified by +object+). Additional options on the input tag can be passed as a 
     179      # hash with +options+.  These options will be tagged onto the html as an HTML element attribute as in the example 
     180      # shown. 
     181      # 
     182      # ==== Examples 
     183      #   password_field(:login, :pass, :size => 20) 
     184      #   # => <input type="text" id="login_pass" name="login[pass]" size="20" value="#{@login.pass}" /> 
     185      # 
     186      #   password_field(:account, :secret, :class => "form_input") 
     187      #   # => <input type="text" id="account_secret" name="account[secret]" value="#{@account.secret}" class="form_input" /> 
     188      # 
     189      #   password_field(:user, :password, :onchange => "if $('user[password]').length > 30 { alert('Your password needs to be shorter!'); }") 
     190      #   # => <input type="text" id="user_password" name="user[password]" value="#{@user.password}" onchange = "if $('user[password]').length > 30 { alert('Your password needs to be shorter!'); }"/> 
     191      # 
     192      #   password_field(:account, :pin, :size => 20, :class => 'form_input') 
     193      #   # => <input type="text" id="account_pin" name="account[pin]" size="20" value="#{@account.pin}" class="form_input" /> 
     194      # 
     195      def password_field(object_name, method, options = {}) 
     196        InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_input_field_tag("password", options) 
     197      end 
     198 
     199      # Returns a hidden input tag tailored for accessing a specified attribute (identified by +method+) on an object 
     200      # assigned to the template (identified by +object+). Additional options on the input tag can be passed as a 
    172201      # hash with +options+.  These options will be tagged onto the html as an html element attribute as in the example 
    173202      # shown. 
    174203      # 
    175       # Examples (call, result): 
    176       #   text_field(:post, :title, :size => 20) 
    177       #     <input type="text" id="post_title" name="post[title]" size="20" value="#{@post.title}" /> 
    178       def text_field(object_name, method, options = {}) 
    179         InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_input_field_tag("text", options) 
    180       end 
    181  
    182       # Works just like text_field, but returns an input tag of the "password" type instead. 
    183       def password_field(object_name, method, options = {}) 
    184         InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_input_field_tag("password", options) 
    185       end 
    186  
    187       # Works just like text_field, but returns an input tag of the "hidden" type instead. 
     204      # ==== Examples  
     205      #   hidden_field(:signup, :pass_confirm) 
     206      #   # => <input type="hidden" id="signup_pass_confirm" name="signup[pass_confirm]" value="#{@signup.pass_confirm}" /> 
     207      # 
     208      #   hidden_field(:post, :tag_list) 
     209      #   # => <input type="hidden" id="post_tag_list" name="post[tag_list]" value="#{@post.tag_list}" /> 
     210      # 
     211      #   hidden_field(:user, :token) 
     212      #   # => <input type="hidden" id="user_token" name="user[token]" value="#{@user.token}" />    
    188213      def hidden_field(object_name, method, options = {}) 
    189214        InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_input_field_tag("hidden", options) 
    190215      end 
    191216 
    192       # Works just like text_field, but returns an input tag of the "file" type instead, which won't have a default value. 
     217      # Returns an file upload input tag tailored for accessing a specified attribute (identified by +method+) on an object 
     218      # assigned to the template (identified by +object+). Additional options on the input tag can be passed as a 
     219      # hash with +options+.  These options will be tagged onto the html as an html element attribute as in the example 
     220      # shown. 
     221      # 
     222      # ==== Examples 
     223      #   file_field(:user, :avatar) 
     224      #   # => <input type="file" id="user_avatar" name="user[avatar]" /> 
     225      # 
     226      #   file_field(:post, :attached, :accept => 'text/html') 
     227      #   # => <input type="file" id="post_attached" name="post[attached]" /> 
     228      # 
     229      #   file_field(:attachment, :file, :class => 'file_input') 
     230      #   # => <input type="file" id="attachment_file" name="attachment[file]" class="file_input" /> 
     231      # 
    193232      def file_field(object_name, method, options = {}) 
    194233        InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_input_field_tag("file", options) 
     
    199238      # hash with +options+. 
    200239      # 
    201       # Example (call, result): 
    202       #   text_area("post", "body", "cols" => 20, "rows" => 40) 
    203       #     <textarea cols="20" rows="40" id="post_body" name="post[body]"> 
    204       #       #{@post.body} 
    205       #     </textarea> 
     240      # ==== Examples 
     241      #   text_area(:post, :body, :cols => 20, :rows => 40) 
     242      #   # => <textarea cols="20" rows="40" id="post_body" name="post[body]"> 
     243      #   #      #{@post.body} 
     244      #   #    </textarea> 
     245      # 
     246      #   text_area(:comment, :text, :size => "20x30") 
     247      #   # => <textarea cols="20" rows="30" id="comment_text" name="comment[text]"> 
     248      #   #      #{@comment.text} 
     249      #   #    </textarea> 
     250      # 
     251      #   text_area(:application, :notes, :cols => 40, :rows => 15, :class => 'app_input') 
     252      #   # => <textarea cols="40" rows="15" id="application_notes" name="application[notes]" class="app_input"> 
     253      #   #      #{@application.notes} 
     254      #   #    </textarea> 
     255      # 
     256      #   text_area(:entry, :body, :size => "20x20", :disabled => 'disabled') 
     257      #   # => <textarea cols="20" rows="20" id="entry_body" name="entry[body]" disabled="disabled"> 
     258      #   #      #{@entry.body} 
     259      #   #    </textarea> 
    206260      def text_area(object_name, method, options = {}) 
    207261        InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_text_area_tag(options) 
     
    212266      # integer is above zero, then the checkbox is checked. Additional options on the input tag can be passed as a 
    213267      # hash with +options+. The +checked_value+ defaults to 1 while the default +unchecked_value+ 
    214       # is set to 0 which is convenient for boolean values. Usually unchecked checkboxes don't post anything. 
    215       # We work around this problem by adding a hidden value with the same name as the checkbox. 
    216       # 
    217       # Example (call, result). Imagine that @post.validated? returns 1: 
     268      # is set to 0 which is convenient for boolean values. Since HTTP standards say that unchecked checkboxes don't post anything, 
     269      # we add a hidden value with the same name as the checkbox as a work around. 
     270      # 
     271      # ==== Examples  
     272      #   # Let's say that @post.validated? is 1: 
    218273      #   check_box("post", "validated") 
    219       #    <input type="checkbox" id="post_validate" name="post[validated]" value="1" checked="checked" /> 
    220       #     <input name="post[validated]" type="hidden" value="0" /> 
    221       # 
    222       # Example (call, result). Imagine that @puppy.gooddog returns "no": 
     274      #   # => <input type="checkbox" id="post_validate" name="post[validated]" value="1" checked="checked" /> 
     275      #     <input name="post[validated]" type="hidden" value="0" /> 
     276      # 
     277      #   # Let's say that @puppy.gooddog is "no": 
    223278      #   check_box("puppy", "gooddog", {}, "yes", "no") 
    224       #     <input type="checkbox" id="puppy_gooddog" name="puppy[gooddog]" value="yes" /> 
    225       #     <input name="puppy[gooddog]" type="hidden" value="no" /> 
     279      #   # => <input type="checkbox" id="puppy_gooddog" name="puppy[gooddog]" value="yes" /> 
     280      #   #    <input name="puppy[gooddog]" type="hidden" value="no" /> 
     281      # 
     282      #   check_box("eula", "accepted", {}, "yes", "no", :class => 'eula_check') 
     283      #   # => <input type="checkbox" id="eula_accepted" name="eula[accepted]" value="no" /> 
     284      #   #    <input name="eula[accepted]" type="hidden" value="no" /> 
     285      # 
    226286      def check_box(object_name, method, options = {}, checked_value = "1", unchecked_value = "0") 
    227287        InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_check_box_tag(options, checked_value, unchecked_value) 
     
    232292      # radio button will be checked. Additional options on the input tag can be passed as a 
    233293      # hash with +options+. 
    234       # Example (call, result). Imagine that @post.category returns "rails": 
     294      # 
     295      # ==== Examples 
     296      #   # Let's say that @post.category returns "rails": 
    235297      #   radio_button("post", "category", "rails") 
    236298      #   radio_button("post", "category", "java") 
    237       #     <input type="radio" id="post_category" name="post[category]" value="rails" checked="checked" /> 
    238       #     <input type="radio" id="post_category" name="post[category]" value="java" /> 
    239       # 
     299      #   # => <input type="radio" id="post_category" name="post[category]" value="rails" checked="checked" /> 
     300      #   #    <input type="radio" id="post_category" name="post[category]" value="java" /> 
     301      # 
     302      #   radio_button("user", "receive_newsletter", "yes") 
     303      #   radio_button("user", "receive_newsletter", "no") 
     304      #   # => <input type="radio" id="user_receive_newsletter" name="user[receive_newsletter]" value="yes" /> 
     305      #   #    <input type="radio" id="user_receive_newsletter" name="user[receive_newsletter]" value="no" checked="checked" /> 
    240306      def radio_button(object_name, method, tag_value, options = {}) 
    241307        InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_radio_button_tag(tag_value, options)