Generating Rails apps is cool. Really cool. It’s push-button web application development.
Yet, push-button development is black box. Sure, running
rails generate scaffold Foobar writes a lot of code… but what does it all mean? Do you know?
Updated June 8, 2011: This article scheduled to be updated for Rails 3.1
I decided to find out for myself…
In search of enlightenment, I’ve constructed, from scratch, what I currently believe is the smallest Rails application possible. This is a worthy exercise, and I’m going to detail every step below.
Ok, this isn’t totally from scratch, as we’re going to use Rails to generate the basic application. We’re just not going to generate any views, controllers, models, or any of that other hooha.
Let’s get started.
1. Setting up the Scratch App
You know the drill:
$ rails new scratch . . . create app/controllers/application_controller.rb create app/helpers/application_helper.rb create app/mailers create app/models create app/views/layouts/application.html.erb . . .
I’m not showing a long list of other actions performed by Rails. Those actions are necessary (mostly) but not germane to our discussion here.
Once we have our initial Rails application, let’s get the Gemfile squared away.
source 'http://rubygems.org' gem 'rails', '3.0.0' gem 'sqlite3-ruby', :require => 'sqlite3' group :development do gem 'rspec-rails', '2.1.0' end group :test do gem 'rspec', '2.1.0' gem 'rspec-rails', '2.1.0' gem 'webrat', '0.7.1' end
Now run bundler:
$ bundle install
Get rid of the
Now you should be able to start the server:
$ rails s
and get a routing error:
No route matches "/"
Makes sense. We don’t even have a web page there.
2. Create a Home page
Let’s create a web page. We’ll start with a Home page, created as a view because we understand web pages really well (controllers, not so much).
$ mkdir app/views/pages $ vi apps/view/pages/home.html.erb
You can add anything you want to this page. I just wrote a single line:
<p>Welcome to your Home Page from Scratch.</p>
Are we there yet?
No. Rails has no way of knowing where to send our request. We need to add a routing directive.
3. Route your request
Now we need to route to it:
$ vi config/routes.rb
add the line
root :to => 'pages#home'
Testing this out results in another rendering error:
uninitialized constant PagesController
Ok, now we’re striking into the core of Rails. We need a controller.
4. Add a Pages controller
This turns out to be very simple:
$ vi app/controllers/pages_controller.rb
As it turns out, we don’t need very much code in the controller:
class PagesController < ApplicationController end
Success! Our page serves.
But we're not done yet, we need to test it.
5. Testing Scratch
rspec to the Gemfile. Let's get
rspec installed and write a test:
$ rails generate rspec:install
So we used generate... it turns out we need a file called
spec_helper.rb and using generate is the fastest way to get that file.
Here's what's in
require 'spec_helper' describe PagesController do render_views describe "GET 'home'" do it "should have the word 'Scratch'" do get :home response.should have_selector("p", :content => "Scratch") end end end
Let's run it:
$ rspec spec . Finished in 0.04513 seconds 1 example, 0 failures $
And that's it. The smallest Rails app possible.
Or at least the smallest Rails App I know how to write.
Making scratch smaller
Here's a number of things to investigate:
- Remove the database completely. It's not needed, but the current configuration barfs without having the SQLite gem bundled. Here are some links for removing database dependency:
- Build the rails code from scratch instead of using
rails new. Could be fun to try.
One of the coolest things about Rails is how easy it is to build a template application to help get yourself bootstrapped. Here are a few resources to help get you started:
Let's hear it from readers: how would you suggest making this code smaller?
Update: After reading just a few pages into RSpec, it occurred to me this development cycle is incorrect. Or at least not state of the art. What did I do wrong?