Form As a Wrapper

The form_for helper method sets up the entire form, creating the HTML form element but also providing context for all of the fields in the form. The form_for method is a bit sneaky, too. Both the new.html.erb view and the edit.html.erb view use form_for the same way:

<% form_for(@person) do |f| %>
...
<% end %>

However, the generated form element looks very different, depending on what exactly is in @person. If @person is just an empty object structure, form_for will work on the assumption that this is to create a new object. If @person actually contains data, however, form_for will assume that its form is editing that object and create a different-looking form element, plus a hidden field to enable Rails’ REST capabilities.

When given an empty @person object, form_for prepares for a new person:

<form action="/people" class="new_person" id="new_person" method="post"><div
style="margin:0;padding:0"><input name="authenticity_token" type="hidden"
value="f80a01b9f14d38e0816877e832637e3cc9e668a1" /></div>

Note that the action goes to people, generically. The class and id reflect a new person, and the method is simply post.

When given an @person object with content, however, form_for switches to editing a person:

<form action="/people/1" class="edit_person" id="edit_person_1" method="post">
<div
style="margin:0;padding:0"><input name="_method" type="hidden" value="put" /><input
name="authenticity_token" type="hidden"
value="f80a01b9f14d38e0816877e832637e3cc9e668a1" /></div>

The action now goes to a URL that includes the ID of the object being edited, and the class and id attributes change values. The method stays at post—but the hidden input with the name _method almost immediately after the form is there to indicate that it should really be treated as a put. (As Chapter 5 noted, browsers don’t all support the HTTP verbs PUT and DELETE, so this input element is designed to help Rails get around that, using POST but indicating that it should be treated differently.)

Rails’ REST capabilities make form_for seem extra smart, but if you’re not creating forms explicitly for a RESTful environment, you need to know a few more things about this method. Underneath, form_for is pretty much a form-specific version of the link_to method shown in Chapter 2. Like link_to, it understands Rails’ routing and will choose its attributes based on that routing.

The form_for method is part of ActionView’s FormHelper module, and the way that Rails’ RESTful scaffolding uses it relies quite completely on its default behavior. Rails takes @person as its one clue to what you want and treats it as a much more complex call to form_for. The form_for object can take more arguments:

A type

Instead of just listing @person and letting form_for guess at the structure we intended, this could have specified :person as the type, followed by the @person object.

A URL

The :url named parameter lets you specify a URL for the action attribute. It’s unlikely that you’ll just point directly to a URL, unless it’s one outside of your Rails application. More typically you’ll ask Rails to create a URL that points to a controller in your application, something like :url => { :action => "celebrate" }.

HTML attributes

The scaffolding populated the form element’s method, class, and id attributes automatically, but if you wanted to specify an id of special_form, a class of my_form, and a method of put, you could specify:

:html => { :id => 'special_form', :class => 'my_form', method => 'put' }

Combined into one, somewhat strange call, this could look like:

<% form_for :person, @person, :url => { :action => "celebrate" },
 :html => { :id => 'special_form', :class => 'my_form',
 method => 'put' } do |f| %>

The form_for method also sets up the variable f, which provides the context all of the other fields will need to do their work, letting you use a shorter form to call their helper methods. (You don’t have to call this variable f, but it’s a conveniently short while still memorable-enough name.)

Also, Rails has created an input element named authenticity_token, which is based on the session ID. Rails uses this internally to minimize cross-site request forgery (CSRF) attacks, as discussed in Chapter 18. This only gets used for PUT, POST, and DELETE requests—GET requests should all be safe by design. (If, of course, you designed your application so that GET requests just return information, not change it.)

Note

If other developers want to script your Rails application from the outside, they certainly can—that’s what the XML side of REST is for.

Finally, you should know that you can create forms in Rails applications without using form_for. You can, of course, create HTML forms by hand. Rails also offers the form_tag method for creating forms as well as a set of form field helper methods (also ending in _tag) if you want to create forms programmatically, but aren’t binding them directly to a model.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset