#184 Formtastic Part 1
- Download:
- source codeProject Files in Zip (104 KB)
- mp4Full Size H.264 Video (14.7 MB)
- m4vSmaller H.264 Video (10.3 MB)
- webmFull Size VP8 Video (24.9 MB)
- ogvFull Size Theora Video (19.1 MB)
If you find writing the view code for forms rather long-winded, you’ll be pleased to know that there’s a gem called Formtastic which provides a more concise way to do it. With it, fairly complex forms can be created with relatively little code as we’ll show you in this episode.
Creating The Vet App
Before we get started with Formtastic it’s worth mentioning a TextMate bundle that’s available. This provides a number of useful snippets that can make creating forms even easier.
To demonstrate Formtastic we’re going to create a new Rails app. This application will keep track of animal patients in a vet’s surgery, so we’ll call it vet
and create it in the normal way.
<p>Formtastic is supplied as a gem. We can include it in our application by adding the following line to our application’s <code>/config/environment.rb</code> file. (If you’re using TextMate and you’ve installed the Formtastic bundle you can use <code>ftgem</code> and <code><TAB></code> as a shortcut).</p> ``` ruby config.gem 'justinfrench-formtastic', :lib => 'formtastic', :source => 'http://gems.github.com'
To make sure the gem is installed we just need to run
``` terminal sudo rake gems:install<p>and then we’re ready to begin writing our application.</p> <p>Our application will make use of some of Ryan Bates’ <a href="http://github.com/ryanb/nifty-generators">nifty generators</a> to make it easier to write parts of the application. The one we’ll use first is the <code>nifty_layout</code> generator which we’ll use to create a layout file and stylesheet.</p> ``` terminal script/generate nifty_layout
Next we’ll generate our first model, making use of the nifty_scaffold
generator to create a controller and views to go with it. We’re going to put our animals into categories so we’ll call our model Category
and give it name
and description
attributes.
<p>We can now migrate our database.</p> ``` terminal rake db:migrate
If we start up our new application and navigate to the new category page we’ll see the scaffold-generated view code.
The code generated by the scaffolding for the form above is this:
``` ruby <% form_for @category do |f| %> <%= f.error_messages %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :description %>
<%= f.text_area :description, :rows => 5 %>
<%= f.submit "Submit" %>
<% end %><p>This is normal Rails form code, starting with a <code>form_for</code> and with each field in the form defined separately along with its label. Finally there’s a submit button so that we can add a new category.</p> <p>Formtastic doesn’t override any of these standard form methods so we can still use them in a Formtastic form. If we replaced the <code>form_for</code> in the form above with Formtastic’s <code>semantic_form_for</code> the form would work just the same. There’s not much point in doing that, however; the real advantage comes when we use Formtastic’s form methods. With them we can change our form to look like this:</p> ``` ruby <% semantic_form_for @category do |f| %> <%= f.inputs %> <%= f.buttons %> <% end %>
The inputs
method is a convenient way to generate all the input fields for a model and, likewise, the buttons
method generates a submit button. If we reload the form now it’ll look a little different.
This form is now rendered using Formtastic’s form methods. The most noticeable difference is that whereas the scaffold-generated form used paragraph tags to separate the fields Formtastic uses ordered lists and fieldsets to separate the input fields from the button.
The form doesn’t look particularly pretty as it stands, but we can fix this by applying some CSS. Formtastic comes with some existing stylesheets that we can generate to save us having to do all of the work ourselves. If we run
``` terminal script/generate formtastic_stylesheets<p>two new stylesheets will be created in our application’s <code>/public/stylesheets</code> directory and we can then reference these new stylesheets from our layout file. In the head section of our layout we’re referencing one stylesheet already.</p> ``` ruby <head> <title><%= h(yield(:title) || "Untitled") %></title> <%= stylesheet_link_tag 'application' %> <%= yield(:head) %> </head>
We can add the two Formtastic stylesheets here to include them on every page in our application.
``` ruby <%= stylesheet_link_tag 'application', 'formtastic', 'formtastic_changes' %><p>The second file, <code>formtastic_changes</code>, is where we should make any changes to the default styles provided in the other stylesheet. As we now have multiple stylesheets we should make use of Rails’ caching option so that the files are combined into one when the application is run in production mode. (This applies to multiple JavaScript files as well.)</p> ``` ruby <%= stylesheet_link_tag 'application', 'formtastic', 'formtastic_changes', :cache => 'base' %>
Using caching like this will mean that fewer files need to be requested from the server when the page loads as the three stylesheet files will be combined into one called base.css
.
If we reload the form now it’ll look a little better, but it’s still not quite how it’s supposed to look.
This is due to a couple of lines in Formtastic’s stylesheet.
``` terminal html[xmlns] form.formtastic fieldset { display: block; } html[xmlns] form.formtastic fieldset ol li { display: block; }<p>The two CSS selectors above expect the pages’ opening <code><html></code> tag to have an <code>xmlns</code> attribute. In the layout file generated by the nifty_layout generator the tag doesn’t have this so we’ll have to add it to get the form to display as it should.</p> ``` terminal <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
Reload the form now and we’ll see the text fields line up as we’d expect them to. Now that we have the form looking as it should we can add a couple of categories, one for dogs and one for cats. We’ll use these shortly when we create the form for the animals themselves.
A More Complex Example
We’ll move on now to the form for the animals. As we did with the categories we’ll start by generating a scaffold.
``` terminal script/generate nifty_scaffold animal name:string category_id:integer born_on:date female:boolean<p>The <code>Animal</code> model will have <code>name</code>, <code>born_on</code> and <code>female</code> attributes along with a <code>category_id</code> so that we can put each animal into a <code>Category</code>. After creating the scaffold we’ll migrate our database again so that the new table is created in the database.</p> ``` terminal rake db:migrate
The next step is to set up the relationship between the models so that an animal belongs to a category…
``` terminal class Animal < ActiveRecord::Base attr_accessible :name, :category_id, :born_on, :female belongs_to :category end<p>…and a category has many animals.</p> ``` ruby class Category < ActiveRecord::Base attr_accessible :name, :description has_many :animals end
The form generated by the scaffolding is shown below. We want to replace this with some Formtastic code so we’ll be changing this soon.
As we did with the category form we’ll be replacing the default form_for
code with a Formtastic semantic_form_for
form.
<p>We want a little more control over our form fields this time as we’re going to customise them shortly so we’ve passed <code>f.inputs</code> a block, inside of which we’ve used the <code>input</code> method to define each field. After we’ve closed the block we can add our submit button with <code>f.buttons</code> as we did before.</p> <p>If we reload the form now we’ll see the fields as rendered by Formtastic.</p> <div class="imageWrapper"> <img src="http://railscasts.com/static/episodes/asciicasts/E184I06.png" width="801" height="477" alt="The New Animal page with the Formtastic controls on it."/> </div> <p>Formtastic has created appropriate form fields according the the <code>Animal</code> model’s attributes’ types. Although you can’t see it here it has even worked out that the <code>category_id</code> field is a association and populated the category dropdown with the two categories we added earlier.</p> <p>There are a few changes we want to make to this form. By default, the year part of the date field is only populated five years either side of the current year and we need to show dates further back than that. Also, we want to remove the blank option from the <code>category</code> dropdown and show the <code>female</code> field as a pair of radio buttons rather than as a checkbox.</p> <p>We can customise fields by using the same options that we pass to Rails’ form helper methods. This means that we can pass <code>born_on</code> a <code>:start_year</code> and use an <code>:include_blank => false</code> parameter in our category to remove the blank option.</p> ``` ruby <% semantic_form_for @animal do |f| %> <% f.inputs do %> <%= f.input :name %> <%= f.input :born_on, :start_year => 1900 %> <%= f.input :category, :include_blank => false %> <%= f.input :female, :as => :radio %> <% end %> <%= f.buttons %> <% end %>
We have to treat the female
field a little differently as we’re changing the type of form element. To specify a different type of field from the default Formtastic has an :as
parameter. We can use :as => :radio
to change the type to radio buttons.
If we take another look at the form now we’ll see the changes we made reflected there, with the dates starting from 1900, the blank option removed from the category and the female checkbox replaced by two radio buttons.
The radio buttons are an improvement on the checkbox, but instead of “yes” and “no” we’d like the field to be labelled “Gender” and the radio buttons labelled “Male” and “Female”. Does Formtastic allow this level allow this level of customisation? It does. We can make use of the :label
and :collection
options to set the values of the label and the radio buttons.
As the name implies the :label
option sets the name of the label, while the :collection
option takes a array of arrays specifying the name and value of each radio button.
The form now looks just how we want it to.
Our form is now complete and we can use it to create as many new animals as we want.
Taking it Further
With Formtastic we have successfully created a fairly complex form with relatively little view code, using its customisation options to alter some of the fields to suit our needs. There’s still quite a bit of Formtastic that we haven’t covered though so we’ll be going into it in more depth in the next episode.