Improved Scaffolding for Ruby on Rails

Using the ActiveScaffold plugin to improve the default Ruby on Rails layouts.

Creating the Database Tables with Rails

Rails can help with the creation of our database tables, and we
need three: one to hold information on our soccer players, another for
squad data and another to maintain medical conditions. For the sake of
simplicity, let's assume that each player belongs to one squad and can
have a single medical condition (or none at all). Let's tell Rails about
the tables:

Models in Rails let us talk to our data from our Web application. Each
of the above commands produces eight lines of output while Rails does
its thing. Note that each contains a file generated in the db/migrate
directory. These are our database migrations. At this point, things
get less SQL-centric and more Rails-like, as Rails provides a database-independent way to define our tables. To see this in action, edit the
db/migrate/xxxxxxxxx_create_players.rb file (where xxxxxxxxx is a
unique date/time string generated by Rails), changing the self.up method
to look like this:

This is the high-level Rails way of telling your database to create a
table. Each column in the table gets a unique name and a data type. Note
that in addition to the columns you might expect each player to have
(name, address and so on), we add in two integer columns that will
link to the squad and condition tables. What's cool about using
migrations is that it does not matter which database you are using,
Rails generates the correct database-specific SQL statements as
required and when needed. Let's define the other two tables. Edit
db/migrate/xxxxxxxxxx_create_squads.rb, changing the self.up method
as follows:

What's happened is that Rails has connected to the back-end database and
created the three required tables. Note that there's no programmer-written
SQL code in sight! Rails handles all the down-and-dirty SQL details. For
those readers who don't believe me, log in to PostgreSQL as soccer_manager
and bask in the glory of the table schema that Rails has created for you.

The Default Rails Layouts

At this point, it would be normal to use Rails to generate some
scaffolding code, then reach for a CSS reference to pretty up the whole
thing. This is doable, but it takes time. For now, let's use Rails to
generate empty controllers with these three commands:

Each of these commands produces seven lines of output. Note that a Ruby
file is generated in the app/controllers directory. These are source
code files that will contain any business logic we want to add to
our Rails application. We will do this in a little while. To complete the
default Rails setup, we need to specify our table relationships. Edit
app/models/player.rb to look like this:

ActiveScaffold is written and maintained by a dedicated group of Rubyists
who live at activescaffold.com/team. ActiveScaffold is a Rails
plugin, and as such, gets installed into an existing Rails project,
so let's do that first. From the top-level directory of your Rails
application, type the following (which should be entered on a single
line):

This command fetches ActiveScaffold and installs it into your Rails
application. When this process completes, a new directory has been
created within the vendor/plugins/ directory of your Rails application
called activescaffold. For the plugin to work its magic, we need to
create an application-level layout that will be used throughout our Rails
application. Here's a bare-bones layout, which we need to create in the
app/views/layouts directory and which is called application.rhtml:

This is a straightforward, essentially empty, HTML page. Take note of
the code included within the <%= and %> tags. These tags allow us to
execute Ruby code from within an HTML template. The first set of such tags
adds a set of JavaScript routines to our page; the second pulls in the
ActiveScaffold goodness, and the third executes the Ruby yield method. Any
layouts that are created within our application (whether manually by
us or dynamically by Rails or ActiveScaffold) will be wrapped in the
application.rhtml layout, with their content replacing the invocation of
yield as required. With the default layout created, we need to edit each
of our existing controllers to switch on ActiveScaffold. Here's how the
app/controllers/player_controller.rb file should appear after this edit:

Add a similar line of code to the app/controllers/squad_controller.rb
and app/controllers/condition_controller.rb files, then start your
Rails application:

ruby script/server

Fire up your browser and load the http://localhost:3000/player page. Take
a look at Figure 1, which shows the default ActiveScaffold player
listing—it looks great. Note that ActiveScaffold has spotted the links between
the three tables and pulled in the appropriate data values. Note also
that I've added some sample data to my Web app. Unfortunately, the
ordering of the columns leaves a little to be desired, and this is no
more evident than when we view the default ActiveScaffold player form, as
shown in Figure 2. This form displays the table columns in alphabetical
order, which is not what we want. In addition, the subforms that
provide access to the squad and medical condition data are cool, but
what we want is a simple drop-down list for our application. Thankfully,
adjusting ActiveScaffold's default behaviors is not difficult, as we
shall see in a few moments.

Another problem (which you may have noticed if you've been following
along) is that the date range associated with the date_of_birth value
is very restrictive, using 1997 as the earliest start year. As all of
our soccer players were born in the early 1990s, we need some way to
adjust the start year for any entered dates. ActiveScaffold (together
with Rails) can help here too.

Figure 1. Default Player Listing as Generated by ActiveScaffold

Figure 2. Default Player Data-Entry Form as Generated by ActiveScaffold

A reader, Ken Shaffer, emailed with an issue he had getting the example code (above) to work with his version of PostgreSQL. I initially suggested he try it with MySQL just to get things going but, to Ken's credit, he soldiered on and sorted out his problems. Here's a copy of Ken's e-mail to me letting me know what he did. Both Ken and I hope this information will be of use to other readers experiencing similar problems.

----------- start of Ken's email -----------
Hi Paul,
I did succeed in getting a compatible set of gems and activescaffold
for running the soccer club demo. Open source is so dynamic
that it's sometimes tricky getting compatible versions of things --
my hat's off to the people putting Linux distributions together.

For the Ubuntu 8.10 rails 2.1 (rake, rubygems) installed via the
Synaptic Package Manager, use the ruby_pg gem instead of the postgres
gem.
I understand the postgres gem has not been supported since 2006.
Also avoid the pg gem, which is not necessary. The activescaffold
install now needs to pick out the rails 2.1 (previous) version.
The following failed to get the rails 2.1 version (got the default 2.2
ver):
script/plugin install \
git://github.com/activescaffold/active_scaffold.git \
-r rails-2.1
Found a code snippit (attached below) which worked.

Another (more painful) approach which worked is to update all the
rails 2.1.0 versions to the 2.2.2 versions (and also update rubygems).
The default activescaffold install will then work.

The below code snippit succeeded in getting the activescaffold version
compatible with rails 2.1

Again, thanks for a great article. It was the combination of postgresql
and rails that caught my interest. Feel free to pass along any info, no
attribution needed.
Ken
----------- end of Ken's email -----------

Sponsored by:

Geek Guides

Pick up any e-commerce web or mobile app today, and you’ll be holding a mashup of interconnected applications and services from a variety of different providers. For instance, when you connect to Amazon’s e-commerce app, cookies, tags and pixels that are monitored by solutions like Exact Target, BazaarVoice, Bing, Shopzilla, Liveramp and Google Tag Manager track every action you take. You’re presented with special offers and coupons based on your viewing and buying patterns. If you find something you want for your birthday, a third party manages your wish list, which you can share through multiple social- media outlets or email to a friend. When you select something to buy, you find yourself presented with similar items as kind suggestions. And when you finally check out, you’re offered the ability to pay with promo codes, gifts cards, PayPal or a variety of credit cards.