14.1. The Data-Input Workflow

To understand forms we take a look at the data workflow. Understanding it better will help to understand the work of forms.
Example application:
$ rails new testapp
$ cd testapp
$ rails generate scaffold Person first_name last_name
$ rake db:migrate
$ rails s
=> Booting WEBrick
=> Rails 4.0.0 application starting in development on
=> Run `rails server -h` for more startup options
=> Ctrl-C to shutdown server
[2013-07-20 09:48:23] INFO  WEBrick 1.3.1
[2013-07-20 09:48:23] INFO  ruby 2.0.0 (2013-06-27) [x86_64-darwin12.4.0]
[2013-07-20 09:48:23] INFO  WEBrick::HTTPServer#start: pid=72655 port=3000
Most times we create forms by using the Scaffold. Let's go through the flow the data

Request the people#new form

Wenn we request the URL the router answers the following route:
new_person GET    /people/new(.:format)      people#new
The controller app/controllers/people_controller.rb runs this code:
# GET /people/new                                                             
def new
  @person = Person.new
So a new Instance of Person is created and stored in the instance variable @person.
Rails takes @person and starts processing the view file app/views/people/new.html.erb
<h1>New person</h1>

<%= render 'form' %>

<%= link_to 'Back', people_path %>
render 'form' renders the file app/views/people/_form.html.erb
<%= form_for(@person) do |f| %>
    <%= f.text_field :first_name %>
    <%= f.text_field :last_name %>
    <%= f.submit %>
<% end %>
form_for(@person) embeddeds the two text_fields :first_name and :last_name plus a submit Button.
The resulting HTML:
<form accept-charset="UTF-8" action="/people" class="new_person" id="new_person" method="post">
    <input id="person_first_name" name="person[first_name]" type="text" />
    <input id="person_last_name" name="person[last_name]" type="text" />
    <input name="commit" type="submit" value="Create Person" />
This form uses the post method to upload the data to the server.

Push the Data to the Server

We enter 'Stefan' in the first_name field and 'Wintermeyer' in the last_name field and click the submit button. The browser uses the post method to uploads the data to the URL /people. The log shows:
Started POST "/people" for at 2013-07-20 10:14:02 +0200
Processing by PeopleController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"cIZ+XFBx75mnXb6WiVv4xj6S88ahPjwVedDg1YgGuJs=", "person"=>{"first_name"=>"Stefan", "last_name"=>"Wintermeyer"}, "commit"=>"Create Person"}
   (0.1ms)  begin transaction
  SQL (4.6ms)  INSERT INTO "people" ("created_at", "first_name", "last_name", "updated_at") VALUES (?, ?, ?, ?)  [["created_at", Sat, 20 Jul 2013 08:14:02 UTC +00:00], ["first_name", "Stefan"], ["last_name", "Wintermeyer"], ["updated_at", Sat, 20 Jul 2013 08:14:02 UTC +00:00]]
   (0.9ms)  commit transaction
Redirected to
Completed 302 Found in 10ms (ActiveRecord: 5.5ms)
What happend in Rails?
The router answers the request with this route
POST   /people(.:format)          people#create
The controller app/controllers/people_controller.rb runs this code
# POST /people
# POST /people.json
def create
  @person = Person.new(person_params)
    if @person.save
      format.html { redirect_to @person, notice: 'Person was successfully created.' }

# Never trust parameters from the scary internet, only allow the white list through.
def person_params
  params.require(:person).permit(:first_name, :last_name)
A new instance variable @person is created. It represense a new Person which was created with the params that were send from the browser to the Rails application. The params are checked in the person_params method which is a whitelist. That is done so the user can not just inject params which we don't want to be injected.
Once @person is saved a redirect_to @person is triggered. That would be in this example.

Present the new Data

The redirect to is traceable in the log file
Started GET "/people/1" for at 2013-07-20 10:14:02 +0200
Processing by PeopleController#show as HTML
  Parameters: {"id"=>"1"}
  Person Load (0.2ms)  SELECT "people".* FROM "people" WHERE "people"."id" = ? LIMIT 1  [["id", "1"]]
  Rendered people/show.html.erb within layouts/application (1.1ms)
Completed 200 OK in 9ms (Views: 5.3ms | ActiveRecord: 0.2ms)
The router answers to this request with
person GET    /people/:id(.:format)      people#show
Which gets handled be the show method in app/controllers/people_controller.rb

Thank you for your support and the visibility by linking to this website on Twitter and Facebook. That helps a lot!