Flowdock

Form helpers are designed to make working with resources much easier compared to using vanilla HTML.

Forms for models are created with form_for. That method yields a form builder that knows the model the form is about. The form builder is thus able to generate default values for input fields that correspond to model attributes, and also convenient names, IDs, endpoints, etc.

Conventions in the generated field names allow controllers to receive form data nicely structured in params with no effort on your side.

For example, to create a new person you typically set up a new instance of Person in the PeopleController#new action, @person, and pass it to form_for:

<%= form_for @person do |f| %>
  <%= f.label :first_name %>:
  <%= f.text_field :first_name %><br />

  <%= f.label :last_name %>:
  <%= f.text_field :last_name %><br />

  <%= f.submit %>
<% end %>

The HTML generated for this would be (modulus formatting):

<form action="/people" class="new_person" id="new_person" method="post">
  <div style="margin:0;padding:0;display:inline">
    <input name="authenticity_token" type="hidden" value="NrOp5bsjoLRuK8IW5+dQEYjKGUJDe7TQoZVvq95Wteg=" />
  </div>
  <label for="person_first_name">First name</label>:
  <input id="person_first_name" name="person[first_name]" size="30" type="text" /><br />

  <label for="person_last_name">Last name</label>:
  <input id="person_last_name" name="person[last_name]" size="30" type="text" /><br />

  <input name="commit" type="submit" value="Create Person" />
</form>

As you see, the HTML reflects knowledge about the resource in several spots, like the path the form should be submitted to, or the names of the input fields.

In particular, thanks to the conventions followed in the generated field names, the controller gets a nested hash params[:person] with the person attributes set in the form. That hash is ready to be passed to Person.create:

if @person = Person.create(params[:person])
  # success
else
  # error handling
end

Interestingly, the exact same view code in the previous example can be used to edit a person. If @person is an existing record with name “John Smith” and ID 256, the code above as is would yield instead:

<form action="/people/256" class="edit_person" id="edit_person_256" method="post">
  <div style="margin:0;padding:0;display:inline">
    <input name="_method" type="hidden" value="put" />
    <input name="authenticity_token" type="hidden" value="NrOp5bsjoLRuK8IW5+dQEYjKGUJDe7TQoZVvq95Wteg=" />
  </div>
  <label for="person_first_name">First name</label>:
  <input id="person_first_name" name="person[first_name]" size="30" type="text" value="John" /><br />

  <label for="person_last_name">Last name</label>:
  <input id="person_last_name" name="person[last_name]" size="30" type="text" value="Smith" /><br />

  <input name="commit" type="submit" value="Update Person" />
</form>

Note that the endpoint, default values, and submit button label are tailored for @person. That works that way because the involved helpers know whether the resource is a new record or not, and generate HTML accordingly.

The controller would receive the form data again in params[:person], ready to be passed to Person#update_attributes:

if @person.update_attributes(params[:person])
  # success
else
  # error handling
end

That’s how you typically work with resources.

Show files where this module is defined (1 file)
Register or log in to add new notes.