Friday, May 2, 2008

Agile Web Development With Rails 3rd Ed. covers Rails 2.0!

The tireless Pragmatic programmers have released a new version of Agile Web Development with Rails, and it covers Rails 2.0!

Its still in beta form, but you can get the PDF version online. If you bought a copy of the 2nd edition since March 2008 you can get a coupon for a free upgrade.

See the pragmatic web site for details.

Friday, February 29, 2008

Rails 2.0 Step by Step (part 2.1)

Rails 2.0 Step by Step (part 2.1)

This is a short post to address an error I made in my part 2 post. I posted a bad copy of the index.html.erb file, and I apologize to those of you who read my blog. Thanks to your comments my error was caught.

The correct code you should use in the index.html.erb file is below, just cut and paste this block:

<div id="movie-list">
<h1>Movie Listing</h1>

<table cellpadding="5" cellspacing="0">
<% for movie in @movies %>
<tr valign="top" class="<%= cycle('list-line-odd', 'list-line-even') %>">

<img class="list-one-sheet" src="<%= movie.one_sheet_url %>"/>

<td width="60%">
<span class="list-title"><%= h(movie.title) %></span><br />
<%= h(truncate(movie.description, 80)) %>

<td class="list-actions">
<%= link_to 'Show', movie %>
<%= link_to 'Edit', edit_movie_path(movie) %>
<%= link_to 'Destroy', movie, :confirm => 'Are you sure?', :method => :delete %>
<% end %>
<br />
<%= link_to 'New movie', :action => 'new' %>

Note: I have just gone back and edited part 2 to include this correction.

Sunday, January 27, 2008

Rails 2.0 Step by Step (part 2)

This is the second part of my series.
Part 1 is here.
Thanks for all of the great comments and help.

I think one of the most important comments came from enklare who pointed out that with Rails 2.0 you should explicitly set the database when you create a new Rails app by using the -d flag.

Instead of using the command

work$ rails exchange
use the command

work$ rails -d mysql exchange

To create the exchange app.

( typing 'rails --help' at the command line will give a short list of available options)

This will help Rails configure your application if you have other databases like SQLLite installed.

SQLLite is the default database for Rails as of Rails version 2.0.

Rails 2.0 Step by Step
(part 2)

Model View Controller

The Model View Controller(MVC) design pattern was first described in 1979 by Trygve Reenskaug while working at Xerox on Smalltalk. MVC is not a new syntax construct like an if statement or a data type like an array or int but more a way of looking at how to structure programs and divide the parts up in a logical and useful way.

Following MVC guidelines has been shown to organize applications in a way that makes them easy to manage and maintain. After working with the MVC pattern for a while you will grow to see the benefits that the division of labor produce.
Rails is a strict MVC frame work.

If you stick to the MVC pattern you will find Rails easier to understand and use.


The Model is all about the data. This includes getting the data in and out of the data store. The scaffolding we set up in part one gives us the four basic operation of using a data store Create,
Read, Update and Destroy. Other data centric functionality also goes in the Model. Searching for data, manipulating data, validating input, and possibly editing the data for display (although sometimes this might logically be part of the view as well).


The View renders the Model in an interactive displayable format. It takes the data in the Model and paints it up on the screen for you to see and interact with.


The Controller responds to events communicating with the Model and the View. This is like the Main loop in a state machine waiting for events like user actions or Model data to show up and reacting as the program dictates to those events. Let's look at the Model View and Controller created by the Rails scaffolding, and start updating each of them with our own code.

We'll make changes to the Model and to the view and then get into the controller and migrations in the next installment.

The Model in Rails
The scaffold command created a model in the app/model/ folder called movies.rb.

Look in ~/work/exchange/app/models/movies.rb and you'll see a pretty sparse Model

The file is a Ruby file and the lines
class Movie <>

declare a class named Movie that inherits from class ActiveRecord::Base. Active Record is one of the gems installed along with Rails.

Looking in the Ruby on Rails api documentation for ActiveRecord::Base in the Classes section shows all of the methods, attributes, exceptions and other parts available in class ActiveRecord::Base. We'll see that an instance of the class Movie could be called anything but the Rails convention is to use a variable named movie or @movie. You will see this in code covered below.

The :: symbol is the Ruby scope operator. In ActiveRecord::Base it means that you are referring to the Base of ActiveRecord and not some other base.

We can customize our Model by adding code here just as in earlier versions of Rails. By adding our own code Movie will inherit from and extend the ActiveRecord::Base class.

The line

validates_presence_of :title, :description, :one_sheet_url

will check to make sure that there is, at least, some value entered in the fields on the form.

Let's create a new movie and see how the model behaves when we leave out the description and one sheet image location.

The Model won't allow a new row to be created if these fields are blank. Rails provides many validation features out of the box. The errors are listed at the top of the screen along with a description of the problem encountered and the fields with errors are highlighted in the form.

Taking a cue out of the AWDWR depot app we can check the format of data entered too.

Let's add some data but give the wrong file extension to our image to see how the model handles the input:

The model correctly flags the badly formatted entry as an error and prints a message. Note that the message displayed is the customized message we put in our model's validation "must be a URL for a GIF, JPG, or PNG image".

Fixing the file extension allows the model to accept the presence and format of our input. By fixing this error the Model saves the movie instance as a row in our table.

There are plenty of places to go to learn more about validation in Ruby on Rails. The Rails documentation is also a good resource as well as the models available to do validation.

Placing logic like this in the model, instead of embedding it in the logic for the screen, helps reduce duplication and ensures that all data being entered undergoes the same validation regardless of the interface used to enter the data.

The View in Rails

The view created by our scaffolding is pretty plain. Looking in the /app/views/ directory you will see two directories, layouts and movies. from the exchange directory change into the views directory and you can see them.
exchange$ cd app/views/
exchange/app/views$ ls -p
layouts/ movies/

movies/ has files that correspond to the various pages we have used in this demo so far
exchange/app/views$ cd movies/
exchange/app/views/movies$ ls -p
edit.html.erb index.html.erb new.html.erb show.html.erb

The .html.erb extension tells us that these files are chunks of html with embedded ruby. Looking at the file show.html.erb shows the html and the embedded ruby code.

Comparing this to the successfully created entry above shows where the Title:, Description:, and One sheet url: come from in our html. The parts between the '<%=' and the '%>' are the embedded ruby code. The code here displays the title, description, and one_sheet_url of the movie instance in @movie.

The two pieces of embedded Ruby with 'link_to' at the bottom show the buttons for Edit and Back. This code is where the text 'Edit' and 'Back' come from as well a the path or action for the controller to take when the button is pressed.

For the 'Edit' action the instance @movie is also passed as a parameter.

The 'h' in the '< % = h...% >' is there to strip any unwanted html and is a little beyond the discussion at this point.

Comparing this to the screen you cannot see where is no place for the green text "Movie was successfully created" originates.

The show.html.erb file is also missing the html, head, and body tags needed for a web page.
We'll find these in the layouts directory.
exchange/app/views/movies$ cd ..
exchange/app/views$ cd layouts/
exchange/app/views/layouts$ ls -p

The scaffolding has created a default layout for the movie view called movies.html.erb. This file contains the parts needed to build a valid web page including our DOCTYPE, title, html, head and body tags, as well as where the color green came from for the friendly notice "Movie was successfully created".

The <%= yield %> is where the chunks of html from the files under the /views directory go when a page is built for display. The controller matches the chunk of html from the views/ directory to the action. Listing all of the movies uses the index.html.erb file, creating a new movie uses the new.html.erb file, editing an existing movie uses the edit.html.erb file, and showing one existing movie uses the show.html.erb file.

Also note that our original web page uses a css stylesheet called 'scaffold'.

Customized View
Side Note:
I spend most of my professional time optimizing queries. Sounds exciting, I know. I don't have the gene for good design, so I'll keep it simple. There are plenty of people in the Rails community with great design ideas so there are plenty of better places for you to go to get layout tips.

Add some div id tags to our page and create a simple stylesheet. First change the movies.html.erb

The scaffold command created a stylesheet in the directory /exchange/public/stylesheets called scaffold.css. Create one called exchange.css that looks like

/* Global styles */
/* START:notice */
#notice {
border: 2px solid red;
padding: 1em;
margin-bottom: 2em;

background-color: #f0f0f0;
font: bold smaller sans-serif;
/* END:notice */
/* Styles for main page */
#banner {
background: #0099cc;
padding-top: 10px;
padding-bottom: 20px;
border-bottom: 4px solid;
/* font: small-caps 50px/50px "Times New Roman", serif; */

font: small-caps 50px/50px serif;
color: #000080;
text-align: center;
#banner img {
float: left;
#columns {
background: #9999ff;

#main {
margin-left: 12em;
padding-top: 4ex;
padding-left: 2em;
background: white;
#side {
float: left;

padding-top: 1em;
padding-left: 1em;
padding-bottom: 1em;
width: 10em;
background: #9999ff;
#side a {
color: #00ffff;
font-size: small;

h1 {
font: 150% sans-serif;
color: #226;
border-bottom: 3px dotted #77d;

Starting script/server and pointing your browser to http://localhost:3000/movies should give you something like this

It looks a little nicer, but the listing can be made nicer and we can save some duplication in the edit and new pages with a partial form. (The rails.png logo was put in the /exchange/public/images directory by the rails command when our app was created).


If you compare the new.html.erb and the edit.html.erb files you will see that they are almost exactly the same.

Look at the do loop between the <% form_for(@movie) do |f| %> and <% end %> and the only difference is the text passed in the line with 'f.submit'. The new page has the text "Create" and the edit page has the text "Update".

Make a copy of this section from either file and paste it in a file called _form.html.erb in the same views directory.

Edit the text passed in the 'f.submit' line and use a variable named label_text instead so the /exchange/app/views/movies/_form.html.erb file looks like this

The variable label_text will be passed in from the edit or new pages with the correct value inside. Make the edit.html.erb page look like this

Everything between the form_for do and the end is replaced with the one line
<%= render :partial => "form", :locals => { :f => f, :label_text => "Update"} %>

Similarly , edit the new.html.erb file so it looks like

This will render the partial _form and pass it the local variables and the variable label_text with either the value "Create" or "Update". Let's see if it works by editing one of our existing movies.

Things look the same as before, which is exactly what we wanted.

Creating a new movie also continues to work as before

Making a list, checking it twice
let's make the listing look a little more organized. Edit the index.html.erb file so it looks like this:

<div id="movie-list">
<h1>Movie Listing</h1>

<table cellpadding="5" cellspacing="0">
<% for movie in @movies %>
<tr valign="top" class="<%= cycle('list-line-odd', 'list-line-even') %>">

<img class="list-one-sheet" src="<%= movie.one_sheet_url %>"/>

<td width="60%">
<span class="list-title"><%= h(movie.title) %></span><br />
<%= h(truncate(movie.description, 80)) %>

<td class="list-actions">
<%= link_to 'Show', movie %>
<%= link_to 'Edit', edit_movie_path(movie) %>
<%= link_to 'Destroy', movie, :confirm => 'Are you sure?', :method => :delete %>
<% end %>
<br />
<%= link_to 'New movie', :action => 'new' %>

Then add a section to the exchange.css file for our movie-list div id tag that looks like

#movie-list .list-title {
color: #244;
font-weight: bold;
font-size: larger;

#movie-list .list-one-sheet {
width: 60px;
height: 70px;

#movie-list .list-actions {
font-size: x-small;
text-align: right;
padding-left: 1em;

#movie-list .list-line-even {
background: #ffccff;

#movie-list .list-line-odd {
background: #d0d0d0;

The index.html.erb file should now render a page that looks like

here are a few one sheet images for you to play with (you might have to rename them).

Copies of these images should be placed in the /exchange/public/images/ directory.

What has been done so far?
  • Reviewed the Model View Controller design pattern
  • Added validation rules to our model
  • Added a banner and sidebar to our pages
  • Created a style sheet for our app
  • Used a partial form to get rid of code duplication
  • made a prettier listing for our main index page
  • added some graphics to the /public/images directory

Next time I'll look at the controller and a Rails 2.0 trick for adding new columns in a migration.

Saturday, December 15, 2007

Rails 2.0 and Scaffolding Step by Step

Rails 2.0 step by step.

Ruby on Rails 2.0 was released by the Rails core team on Friday, December 7th. There were quite a few changes in the 2.0 release, including the way that Rails generates scaffolding code. This change will probably cause trouble for people using tutorials written for previous versions of Rails. I hope this tutorial will help readers get started with Rails 2.0 and keep the community of Rails developers growing.

This is the first part of a multi-part tutorial. It will cover enough to get a scaffolded Rails application up and running under Rails 2.0.

This first installment of the tutorial will cover installing Rails and then using Rails to generate a new scaffolded application capable of the four basic database functions of creating, reading, updating, and deleting data. Later installments will cover replacement of scaffolding with actual code that will add to the model view and controller portions of the Rails application. The goal of this first part of the tutorial is to get new users over the changes made to scaffolding in Rails 2.0, and get the basic scaffolded application up and running.

Rails has proven itself to been excellent choice for the needs of most teams and projects.

Note:If you are following a detailed tutorial or book based on earlier rails version, it would probably be best to install an earlier version of Rails for use with that book. For example, the book Agile Web Development with Rails (AWDWR) by Dave Thomas and David Heinemeier Hansson is based on Rails 1.2.x. Instructions on how to install an earlier version of Rails are given later in this tutorial.

Use this tutorial to get started with Rails 2.0 and not older versions.

You will need to have MySQL installed on your system to follow along with this tutorial. You can search the web for the best way to install MySQL on your system, It won't be covered here.

Installing Rails 2.0
Installing Rails 2.0 is done the same way as in 1.2.x versions of rails. There are basically three steps to follow.
  • Install Ruby for your Distro or OS
  • Download and install Ruby gems
  • Use gems to install rails
the Get Rails link and the getting started with rails link have the best available information. Follow these links to get Rails installed on your system.

On my debian machine I used the following commands to install Rails 2.0.

Install Ruby:
Change to the superuser and use the debian package manager to install ruby
# apt-get install ruby irb ri rdoc build-essential

Install Ruby gems:
Then download Ruby gems, the ruby package management software, unpack it, change into the rubygems directory and run the file setup.rb as superuser:
$ tar -xvzf rubygems-0.9.5.tgz
$ cd rubygems-0.9.5
$ su
# ruby ./setup.rb

Use gems to install Rails:
The gem package manager can install Rails and all of its dependencies. As superuser issue the command:
# gem install rails --include-dependencies
INFO: `gem install -y` is now default and will be removed
INFO: use --ignore-dependencies to install only the gems you list
Successfully installed rake-0.7.3
Successfully installed activesupport-2.0.1
Successfully installed activerecord-2.0.1
Successfully installed actionpack-2.0.1
Successfully installed actionmailer-2.0.1
Successfully installed activeresource-2.0.1
Successfully installed rails-2.0.1
7 gems installed
Installing ri documentation for rake-0.7.3...
Installing ri documentation for activesupport-2.0.1...
Installing ri documentation for activerecord-2.0.1...
Installing ri documentation for actionpack-2.0.1...
Installing ri documentation for actionmailer-2.0.1...
Installing ri documentation for activeresource-2.0.1...
Installing RDoc documentation for rake-0.7.3...
Installing RDoc documentation for activesupport-2.0.1...
Installing RDoc documentation for activerecord-2.0.1...
Installing RDoc documentation for actionpack-2.0.1...
Installing RDoc documentation for actionmailer-2.0.1...
Installing RDoc documentation for activeresource-2.0.1...

Checking the version of Rails at the command line should give a version number for Rails:
$ rails -v
Rails 2.0.1

If you have trouble installing Rails follow the links above or go to the Rails Forum for help.

Using older versions
If you are using a book like AWDWR from the pragmatic programmers It would probably be best to use an earlier version of Rails. To install a previous version of Rails, use the following command:
# gem install --version=1.2.5 rails --include-dependencies
INFO: `gem install -y` is now default and will be removed
INFO: use --ignore-dependencies to install only the gems you list
Successfully installed activerecord-1.15.5
Successfully installed actionpack-1.13.5
Successfully installed actionmailer-1.3.5
Successfully installed actionwebservice-1.2.5
Successfully installed rails-1.2.5
5 gems installed
Installing ri documentation for activerecord-1.15.5...
Installing ri documentation for actionpack-1.13.5...

$ rails -v
Rails 1.2.5

Updating old versions of Rails
In order to update an older version of Rails to the most current, use the gem command:
$ gem update rails –-include-dependencies

Now let's see how we can get a basic Rails application up and running with a few commands

Using Rails 2.0

Getting started and checking out our installation
Creating a new project in Rails 2.0 starts out much like previous versions. This tutorial uses the example of creating an application to manage the inventory at a local Mom and Pop video rental store, Mom and Pop's Movie Exchange. We'll call the project 'exchange'.

We'll create a directory to keep our work in, change to that directory and use the 'rails' command to create the shell for the exchange application. A great deal of information will flash by on your terminal as Rails creates the basic structure of the application.
$ mkdir work
$ cd work
work$ rails exchange
create app/controllers
create app/helpers
create app/models
create app/views/layouts
create config/environments
create config/initializers
create db
create doc
create lib
create lib/tasks
create log
create public/images
create public/javascripts
create public/stylesheets
create script/performance
create script/process
create test/fixtures
create test/functional
create test/integration
create test/mocks/development
create test/mocks/test
create test/unit
create vendor
create vendor/plugins
create tmp/sessions
create tmp/sockets
create tmp/cache
create tmp/pids
create Rakefile
create README
create app/controllers/application.rb
create app/helpers/application_helper.rb
create test/test_helper.rb
create config/database.yml
create config/routes.rb
create public/.htaccess
create config/initializers/inflections.rb
create config/initializers/mime_types.rb
create config/boot.rb
create config/environment.rb
create config/environments/production.rb
create config/environments/development.rb
create config/environments/test.rb
create script/about
create script/console
create script/destroy
create script/generate
create script/performance/benchmarker
create script/performance/profiler
create script/performance/request
create script/process/reaper
create script/process/spawner
create script/process/inspector
create script/runner
create script/server
create script/plugin
create public/dispatch.rb
create public/dispatch.cgi
create public/dispatch.fcgi
create public/404.html
create public/422.html
create public/500.html
create public/index.html
create public/favicon.ico
create public/robots.txt
create public/images/rails.png
create public/javascripts/prototype.js
create public/javascripts/effects.js
create public/javascripts/dragdrop.js
create public/javascripts/controls.js
create public/javascripts/application.js
create doc/README_FOR_APP
create log/server.log
create log/production.log
create log/development.log
create log/test.log

Rails generates an entire framework for the application. Change into the newly created exchange directory and get to work.
work$ cd exchange
exchange$ ls -p
app/ db/ lib/ public/ README test/ vendor/
config/ doc/ log/ Rakefile script/ tmp/

Setting up the Model and Database Table
At this point many web frameworks would have to use database commands and DDL's to create the table we need to hold our movie inventory data, but thanks to Rails tight coupling between the data and the application we can use Rails to create and manage the tables our project will need. In the Model-View-Controller pattern of application design it's the model that regulates access to the data.

Rails can create the database and tables needed for the exchange project. Look at the file /exchange/config/database.yml, in it you can see the structure of the databases used in Rails:

You can see that there are separate tables for development testing and production. This separation helps in the development and maintenance of Rails projects.

In a difference from earlier Rails versions, Rails 2.0 will create the databases needed with the
exchange$ rake db:create:all
(in /home/sean01/work/exchange)

Starting the web server
Rails includes its own web server, so let's fire it up and see if we have everything working so far.
To start the rails webserver, WEBbrick, use the command:
exchange$ ruby script/server
=> Booting WEBrick...
=> Rails application started on
=> Ctrl-C to shutdown server; call with --help for options
[2007-12-13 12:01:16] INFO WEBrick 1.3.1
[2007-12-13 12:01:16] INFO ruby 1.8.5 (2006-08-25) [i486-linux]
[2007-12-13 12:01:16] INFO WEBrick::HTTPServer#start: pid=3637 port=3000

open your favorite browser and point torwards the URL http://localhost:3000
You should see something like:

Clicking on the 'About your application's environment' link will activate a little piece of AJAX code that lists the particulars of your rails application.

Notice that the default environment is development and not testing or production. This is just what we want during our development phase!

A ctrl-c in the terminal where the WEBbrick server is running will kill the server.

Old vs. New
The next steps show where differences between older Rails tutorials will become greatest. Older tutorials would script/generate a model then use the migrate file created to layout columns in the model's database table. Next you would script/generate a controller and add scaffolding.
This will fail in Rails 2.0.

In Rails 2.0 it will take fewer steps, but may be a little harder to follow because so much is accomplished with so few commands. First we need to think about the movie inventory table.

Start simple. Movies should have, at minimum a title, a description and a movie poster. Columns for other data like release date, rating or quantity on hand can be added later by altering the table through migrations. The next step is to create a model whose job will be to manage the data stored in the database.

The following command will generate the model, plus scaffolding, and the database migration
script needed as well as a controller, helper, and testing support files:

exchange$ ruby script/generate scaffold Movie title:string description:text one_sheet_url:string
exists app/models/
exists app/controllers/
exists app/helpers/
create app/views/movies
exists app/views/layouts/
exists test/functional/
exists test/unit/
create app/views/movies/index.html.erb
create app/views/movies/show.html.erb
create app/views/movies/new.html.erb
create app/views/movies/edit.html.erb
create app/views/layouts/movies.html.erb
create public/stylesheets/scaffold.css dependency model
exists app/models/
exists test/unit/
exists test/fixtures/
create app/models/movie.rb
create test/unit/movie_test.rb
create test/fixtures/movies.yml
create db/migrate
create db/migrate/001_create_movies.rb

create app/controllers/movies_controller.rb
create test/functional/movies_controller_test.rb
create app/helpers/movies_helper.rb
route map.resources :movies

Making Movies

The table will get created by the file in db/migrate/001_create_movies.rb . Let's look at the file

This file will create a table called movies that will be tied to the model Movie. This is a Rails naming convention. A table people would match a model Person. A table cars would match a model Car. You can also see how the parameters we fed the script/generate command show up as table columns and types in this migration file.

Apply this migration to actually create the table with the command:

exchange$ rake db:migrate
(in /home/sean01/work/exchange)
== 1 CreateMovies: migrating ==================================================
-- create_table(:movies)
-> 0.0040s
== 1 CreateMovies: migrated (0.0042s) =========================================

To see what our work so far has produced, start the WEBbrick server with the command (if you didn't kill the earlier one use a control-c to kill it now):

/exchange$ ruby script/server
=> Booting WEBrick...
=> Rails application started on
=> Ctrl-C to shutdown server; call with --help for options
[2007-12-13 17:12:06] INFO WEBrick 1.3.1
[2007-12-13 17:12:06] INFO ruby 1.8.5 (2006-08-25) [i486-linux]
[2007-12-13 17:12:06] INFO WEBrick::HTTPServer#start: pid=4054 port=3000

point your web browse to the URL http://localhost:3000/movies and look at what we have

It looks pretty bare, but we don't have any inventory yet. Click on the 'New Movie' link to start adding some movies to the inventory.

Add a title, description and path to the one-sheet and click Create.

Click the button labeled 'Back' (not the browser back arrow) to return to the main listing and add another movie.

This is still pretty bare bones, but we haven't even written any real code yet!

In database terms CRUD is a good thing. Its an acronym for Create, Read, Update and Delete;
the four most basic functionalities of a data store. The exchange app has this basic functionality without writing one line of code. It isn't pretty at this point an does not have any interesting bits and pieces, but it does work.

What has been done so far?
  • Installed Rails
    #gem install rails --include-dependencies
  • Created an aplication with the rails command
    $rails exchange
  • Created the databases for the application with the rake command
    $ rake db:create:all
  • Used the script/generate command to create the scaffolding for the application
    $ ruby script/generate scaffold Movie title:string description:text one_sheet_url:string
  • Created the database table using the generated migration file
    $ rake db:migrate
  • Started the webserver with the script/server command
    $ ruby script/server
  • Pointed our web browser to the application and started entering and editing data

Part 2
Next time we'll cover some actually coding. We'll look at how to use code in the Model, View, and Controller to alter the exchange application's look and functionality as well as learning about Rails built-in test support.

The purpose of scaffolding is to get started, but scaffolding should be replaced as we add code to our project. The usefulness of scaffolding is that we have an actual functioning application right from the start. We can make a change to the view, and test that nothing else breaks. Then repeat the process adding feature after feature until the application is ready for delivery. Its much easier to make changes to an application that already works than, it is to non-functional code that doesn't give any feed back.