Generating HTML Forms with Scaffolding

Although this application is approaching the point beyond which much generated code becomes more of a hassle than a help, it makes sense to create one last round of scaffolding, replacing the application from the previous chapter. After this, we’ll work within the same application for a while, as this kind of tearing down and rebuilding is only a good idea at the very, very beginning of a project.

To get started, create a new application. Move or rename the old guestbook application to get it out of the way, and then run rails guestbook. In Heroku, just create a new application. Then, run the following clunky mess from the command line at the top level of the newly created application:

script/generate scaffold Person name:string secret:string country:string
email:string description:text can_send_email:boolean graduation_year:integer
body_temperature:float price:decimal birthday:date favorite_time:time

In Heroku, you’ll select Generate from the gear menu and enter all of that except for the script/generate. This kind of long list of data structures in the scaffolding is annoying. It’s hard to type, and what’s worse, if you find that you made a mistake after you’ve already modified the generated code, you have a painful choice.

You can either rerun the scaffolding generation and lose all your changes to the logic, or you can modify the migration, the model, and the views by hand. Rails scaffolding generators just overwrite the old code—there’s no support for more subtle fixes.

Neither of these is a fun way to fix a typo, so remember: when you first generate scaffolding, it’s easier to get things right the first time. This doesn’t mean you need to get everything right all at once—no one ever does—but adding new features to code is generally much more fun than fixing a typo. It may be easiest to set up the command in a text editor and then paste it in after checking it carefully. (You can also find the resulting files for this particular command in ch06/guestbook004.)

Before going further, examine the self.up method in the migration this created in db/migrate/001_create_people.rb, shown in Example 6-1. (It won’t actually be 001_create_people.rb—the 001 will be replaced by a timestamp in newer versions of Rails.)

Example 6-1. Creating a richer table with many data types from a migration

def self.up
    create_table :people do |t|
      t.string :name
      t.string :secret
      t.string :country
      t.string :email
      t.text :description
      t.boolean :can_send_email
      t.integer :graduation_year
      t.float :body_temperature
      t.decimal :price
      t.date :birthday
      t.time :favorite_time

      t.timestamps
    end
  end

As requested, Rails created a structure containing many fields of various types. For now, this will do for a demonstration, though eventually there will be change in the data model that requires change to the migration. Run rake db:migrate, and the migration will build the database table for the application.

Next, it’s time to look at the form that Rails created for making new people, app/views/people/new.html.erb, shown in Example 6-2 with key features highlighted.

Example 6-2. The new.html.erb file contains basic form functionality

<h1>New person</h1>

<%= error_messages_for :person %>

<% form_for(@person) do |f| %>
  <p>
    <b>Name</b><br />
    <%= f.text_field :name %>
  </p>

  <p>
    <b>Secret</b><br />
    <%= f.text_field :secret %>
  </p>

  <p>
    <b>Country</b><br />
    <%= f.text_field :country %>
  </p>

  <p>
    <b>Email</b><br />
    <%= f.text_field :email %>
  </p>

  <p>
    <b>Description</b><br />
    <%= f.text_area :description %>
  </p>

  <p>
    <b>Can send email</b><br />
    <%= f.check_box :can_send_email %>
  </p>

  <p>
    <b>Graduation year</b><br />
    <%= f.text_field :graduation_year %>
  </p>

  <p></para>
    <b>Body temperature</b><br />
    <%= f.text_field :body_temperature %>
  </p>

  <p>
    <b>Price</b><br />
    <%= f.text_field :price %>
  </p>

  <p>
    <b>Birthday</b><br />
    <%= f.date_select :birthday %>
  </p>

  <p>
    <b>Favorite time</b><br />
    <%= f.datetime_select :favorite_time %>
  </p>

  <p>
    <%= f.submit "Create" %>
  </p>
<% end %>

<%= link_to 'Back', people_path %>

Most of this should be familiar, as even the simple model had a form_for, a label, and a text_field. There are some useful new features in the highlighted parts, though. First, at the top of the form, is:

      <%= error_messages_for :person %>

This displays any validation errors in the data fields, an interface component you’ll want to consider carefully as you develop richer data. (Do you want to present error messages at the top? Mixed in with the form? Both?)

The :description, which is intended to be a longer piece of text, gets a textarea to contain it:

      <%= f.text_area :description %>

Similarly, the boolean :can_send_email gets a checkbox:

      <%= f.check_box :can_send_email %>

All of the numbers get plain text_fields, but the date and time are handled differently:

<%= f.date_select :birthday %>
...
<%= f.datetime_select :favoriteTime %>

Rails has its own set of controls for handling the always-thorny problem of entering dates and times. They might not be exactly the approach you prefer, but for now, they’re the default. As you can see in Figure 6-1, they’re easily the most intricate form control Rails generates by default, but using a series of drop-down boxes to specify a date and time isn’t most people’s idea of fun. Replacing them isn’t simple, though.

Basic form generated by Rails scaffolding

Figure 6-1. Basic form generated by Rails scaffolding

Figure 6-1 is a foundation for a form, but it’s also a challenge. Users generally want something that is more exciting that this, and more helpful.

Note

To create especially helpful forms, you’ll likely want to use Ajax, as explored in Chapter 16. However, even without Ajax, there are lots of opportunities for improvement beyond what’s shown here.

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

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