The author, smiling winningly Scott Raymond home

Minimal Rails

23 Jun 2006

It’s been observed that the success of Ruby on Rails isn’t due to any particular technical breakthrough or insight. The framework is basically just a collection of good ideas culled from elsewhere, packaged nicely and explained well, with a heapin’ helping of hype. One of those good ideas is passive code generators: tools that spit out application boilerplate for the developer to modify as needed. On the surface, code generators are simply about cutting keystrokes. But there are subtler implications as well: they lower the barrier to entry for new developers, they encourage consistency (both intra- and inter-project), and they create invitations to best practices, like unit testing.

After installation, code generation is the first thing a new Rails developer experiences: rails myapp. (Unfortunately, the next step for newcomers is usually script/generate scaffold, but that’s another story.) The generators are a large part of what makes Rails welcoming to first-timers, and pleasant for full-timers. And they cement community conventions, which is a huge benefit—every Rails app looks the same in terms of directory structure, file names, and configuration format. Learn how one Rails app is organized, and you’ve learned how they’re all organized.

The Downside of Code Generation

Bells ring; singers sing; abstractions leak. For many Railsers—even experienced ones—generators involve some degree of voodoo. They make it easy to not understand how everything works. What are all those files? What’s actually required, and what’s just convention? The significance isn’t just academic. Someday, you’ll face a bug that requires understanding the generated code.

So let’s void the warranty, crack the case, shun the scripts, and build a Rails app from scratch. You’ll find it’s not hard. A minimal working Rails application needs only six directories, five files, and 19 lines of code—including configuration. Here’s how to do it.

But First

I’ll assume that you’ve got Rails installed and working already (if not, see Curt’s introduction.) I’ll also assume MySQL is installed and accessible with the default permissions (username root; blank password). And we’ll use the excellent Mongrel web server (gem install mongrel) to serve the app. The command line examples are for a Unix-like OS, but the ideas transfer directly to Windows. This example will expect a database named myapp, with one table named people, with one column named name. Go ahead and create a row in the table, with your name in it. Ready? Set?

Go

  1. Create a directory for your application: mkdir myapp; cd myapp
  2. Create six subdirectories: mkdir log public app config app/controllers config/environments
  3. Create the development environment, and leave it blank: touch config/environments/development.rb
  4. Create your environment file, config/environment.rb, and enter this:

    require 'rubygems'
    require_gem 'rails'
    require 'initializer'
    RAILS_ROOT = File.join File.dirname(__FILE__), '..'
    Rails::Initializer.run

    These lines pull in the framework (through the RubyGems package manager) and wind everything up. A stock environment.rb includes much more, providing configuration hooks and code to handle edge cases.

  5. Configure your database by creating config/database.yml:

    development:
      adapter: mysql
      database: myapp

    Rails will assume reasonable defaults: root for the username, a blank password, and localhost for the host.

  6. Set up your routes by creating config/routes.rb:

    ActionController::Routing::Routes.draw do |map|
      map.connect '', :controller => 'people'
    end
  7. Write your application in app/controllers/application.rb:

    class Person < ActiveRecord::Base; end
    
    class PeopleController < ActionController::Base
      def index
        @person = Person.find :first
        render :inline => "Hello, <%= @person.name %>"
      end
    end

    Notice we don’t have an ApplicationController—it’s optional; your controllers can inherit directly from ActionController::Base. And we don’t have the models, helpers, or views directories. They aren’t needed; models can be defined anywhere, including application.rb.

That’s it—the minimal application, stripped it down to the rails. Moment of truth time: start it up by running mongrel_rails start, and then point your browser to http://localhost:3000/. If all is well, you’ll see a hyper-minimal Rails app that exercises the whole stack, M, V, and C. Now stop to consider what’s not there: helpers, views, and model files, a bunch of directories (components, db, doc, lib, script, and vendor), dispatchers, Rake tasks, and tests. All of those things are technically optional. They’re conventional, convenient, and recommended—but not essential.

Now Forget Everything I Just Told You

So is this the real man’s way to write Rails? Hell no. Rails’ generators are there for a reason, and there’s no reason to forgo them in your real work. But it’s a worthwhile exercise to go without them, at least once. Not only will you appreciate the shortcuts more, but your understanding of the framework will be stronger.

Have I overlooked anything else that can be cut? Left out something essential? Let me know!

P.S. Attending RailsConf this weekend in Chicago? I’d love to meet. I’ll be speaking at 10am Saturday morning—please stop by and introduce yourself!