New Series: Rails Application Walkthrough
My wife is a professional photographer with a great eye. She has a natural talent for photography that comes through in her work. Her customers love their pictures, of course, and they love to tell their friends about them. So we had the bright idea to put a page of customer testimonials up on her website. Anyone can bang out a static html page, but where’s the fun in that? Besides, it’s sort of clunky for her to get a quote from a customer, send it to me and then I update the web page. It would be much better if there was some system where a customer, fresh from viewing their online proofs could gush about how wonderful their pictures came out right then and there. Sounds just like a guestbook, doesn’t it? We’ve all seen what happens to them right?
Yup, you guessed it: spam.
What we need is a web app that lets a user submit a testimonial and posts it only when it’s approved. It shouldn’t be hard to write, especially with our new favorite framework, Ruby On Rails.
So let’s get started, er… rolling.
Let’s create our application now:
# rails testimony ... 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/boot.rb create config/environment.rb create config/environments/production.rb create config/environments/development.rb ... #
Next, let’s create the databases.We’ll need the usual triumvirate – dev, test, prod:
mysql> create database testimony_dev; Query OK, 1 row affected (0.02 sec) mysql> create database testimony_test; Query OK, 1 row affected (0.00 sec) mysql> create database testimony_prod; Query OK, 1 row affected (0.00 sec) mysql> grant all privileges on testimony_dev.* to testimonydb@myhost identified by 'super-secret-password' Query OK, 0 rows affected (0.00 sec) mysql> grant all privileges on testimony_test.* to testimonydb@myhost identified by 'super-secret-password' Query OK, 0 rows affected (0.00 sec) mysql> grant all privileges on testimony_prod.* to testimonydb@myhost identified by 'super-secret-password' Query OK, 0 rows affected (0.00 sec)
0.00 sec? Hey, that’s a snazzy machine I have, no? Next, edit config/database.yml to match the databases and the user we just created. Once that’s done, we need to create our first model.
# ./script/generate model testimonial
exists app/models/
exists test/unit/
exists test/fixtures/
create app/models/testimonial.rb
create test/unit/testimonial_test.rb
create test/fixtures/testimonials.yml
create db/migrate
create db/migrate/001_create_testimonials.rb
Before we start writing code or defining the schema for our testimonial, let’s stop and think about it for a bit — after all, rapid development doens’t mean thoughtless development. A testimonial, in essence, is a positive statement about someone or something, affirming the value of a product, event or service. It’s made at a particular point in time, by a customer.
class CreateTestimonials < ActiveRecord::Migration
def self.up
create_table :testimonials do |t|
t.column :email, :string, :nil => false
t.column :testimony, :string, :nil => false, :limit => 1024
t.column :approved, :boolean, :default => nil
t.column :created_on, :date
t.column :updated_on, :date
end
end
def self.down
drop_table :testimonials
end
end
Let’s look at what we’ve got now. We said a testimonial has a who (email), a what (testimony),a when (created_on), and an approval status (approved). Just for auditing, if we care in such a simple application, we’ll use updated_on as the date we approved (or denied) the testimonial. Note that approved is defaulted to nil. This allows us to find entries that have been neither approved or denied. If we had a simple true/false state for approved, we would not be able to tell new testimonials from old, unwanted ones. Makes sense to me. You can go ahead and create the table in the usual fashion, using rake db:migrate
Last thing we’ll do tonight is generate the controller, complete with scaffolding:
# ./script/generate scaffold testimonial testimonial
exists app/controllers/
exists app/helpers/
create app/views/testimonial
exists app/views/layouts/
exists test/functional/
dependency model
exists app/models/
exists test/unit/
exists test/fixtures/
identical app/models/testimonial.rb
identical test/unit/testimonial_test.rb
identical test/fixtures/testimonials.yml
create app/views/testimonial/_form.rhtml
create app/views/testimonial/list.rhtml
create app/views/testimonial/show.rhtml
create app/views/testimonial/new.rhtml
create app/views/testimonial/edit.rhtml
create app/controllers/testimonial_controller.rb
create test/functional/testimonial_controller_test.rb
create app/helpers/testimonial_helper.rb
create app/views/layouts/testimonial.rhtml
create public/stylesheets/scaffold.css
#
That wasn’t so bad, was it? Fire up the server, browse to http://testimonials.snowmoonsoftware.com/testimonial and you’ll see the following:
Listing testimonials
| Testimony | Approved | Created on | Updated on |
|---|
Go ahead and click “New testimonial” and add one. I did:
Testimonial was successfully created.
Listing testimonials
| Testimony | Approved | Created on | Updated on | ||||
|---|---|---|---|---|---|---|---|
| testuser@testdomain.com | This is a “test”-imonial. | false | 2007-09-05 | 2007-09-05 | Show | Edit | Destroy |
As usual, since we haven’t done anything with the view, it’s ugly. Functional, but ugly. We’ll take care of that at a later date.
Quick recap
What did we accomplish today? We
- Staked out our requirements
- Generated our application (
rails testimony) - Created and configured our databases (
mysql create) - Created a stub of our testimonial model (
script/generate) - Took a deep breath and thought about the essence of a testimonial and used that to define our model.
- Created the table defined by our model (
rake db:migrate) - Generated a controller and view with built in CRUD support (
script/generate scaffold)
Not too bad, eh?
To be continued…
Filed under: Rails, walkthrough, webdev

[...] Part II: Posted on September 9th, 2007 by Jeff [This is part II of the Testimony Rails Application Walkthrough [...]