With Rails 1.1 now on the streets, I’m upgrading a few apps today. Absorbing all 500 enhancements and fixes into my deep inner matrix will take a while. We’ve been using the major new features on a project that uses Edge Rails for a while now, and there’s documentation floating around for those big-ticket enhancements. But I’m also finding a slew of obscure—dare I say less appreciated—bits and bobs.

I suspect we’ll still be finding these treasures buried beneath the big glossy features for weeks to come. Meanwhile, in the interest of perhaps saving someone else precious time, I’ll update this post throughout the day with the surprises I uncover.

No More White Screen Of Death!

Oh my am I thankful for this fix. I don’t know a person who hasn’t been bit by this (usually more than once), and it’s really frustrating for students. There used to be various ways to trigger a WSOD, usually by mucking with session management. Your reward was a blank (totally empty source) web page.

One path to the WSOD was to inadvertently remove or rename the directory that contained session files. And when Rails couldn’t find its sessions, it wasn’t happy. Now you get a helpful error message on the page:

directory script/../config/../tmp/sessions does not exist

Another way to evoke the WSOD was to put something in your session at some point that couldn’t be loaded later. For example, you’d add a valid model object to the session, then remove or rename it because you had a better idea. Then when the session was hydrated, the object in the session couldn’t be loaded. The fangs came out. In Rails 1.1 you get a helpful error message on the page, for example:

Session contains objects whose class definition isn't available.
Remember to require the classes for all objects kept in the session.
(Original exception: uninitialized constant Product [NameError])

I’ll enjoy all the cool new features, but this bit of polishing is very much appreciated.

Minimalist Database Configuration

By default, the generated config/database.yml file now just includes a configuration for MySQL. It used to have examples for every database adapter, which was a bit much to wade through and more than a little daunting for the newbie. If MySQL isn’t your game, you can specify a database using, for example:

rails myapp --database=postgresql

In this example, the resulting config/database.yml file will be configured for PostgreSQL.

And I’m happy to see that the MySQL socket isn’t being gleaned and set by default. That one had a nasty bite.

Application-Specific JavaScript

You’ll notice a new public/javascripts/application.js file being generated. This is home for your application-specific JavaScript (if you write any JS at all now that RJS is in town).
And by having it in a standard file name, it’s automatically included when you use javascript_include_tag :defaults.

Lighty Needs An Upgrade

I was running version 1.4.8, which gives this error:

Undefined config variable: var.CWD
2006-03-28 09:05:15: (configfile.c.800) source: 
config/lighttpd.conf line: 
8 pos: 43 parser failed somehow near here: + 

Lighty version 1.4.11 is now required by the generated config/lighttpd.conf file. After upgrading to 1.4.11, you’ll need to delete any existing config/lighttpd.conf file and let Rails generate a new one.

If you’ve crafted your own config file and didn’t use CWD, then you’re isolated from this change. But it’s not a bad idea to stay on top of the latest Lighty anyway.

Verbose Migrations

Silence may be golden, but when running migrations you usually want some feedback about what’s going on. Jamis built a verbose migrations plugin, which proved so incredibly handy that he rolled it into core. So for no extra charge at all, you get:

$ rake db:migrate

== Products: migrating
-- create_table(:products)
   -> 0.0068s
== Products: migrated (0.0081s)

== AddPrice: migrating
-- add_column(:products, :price, :float, {:default=>0.0})
   -> 0.0575s
== AddPrice: migrated (0.0584s)

...

New Temporary Directories

Three new temporary directories are created by default:

tmp/cache
tmp/sessions
tmp/sockets

The directory contents should be self-explanatory. Previously we were defining custom directories for the first two (session and cache files) in order to keep them in a well-known, application-specific location. Prior to 1.1, session files were all housed in a global temp directory by default, which made cleaning ‘em up prone to error.
I like to be able to float between projects and consistently find stuff. You can clear out all the temp files using:

$ rake tmp:clear

Auto-Generated Migrations

Generating a model automatically triggers the generation of a migration file for that model:

$ script/generate model account 
  ...
  create  db/migrate/001_create_accounts.rb

I generally think through the model by writing the migration file first and running the migration. Then I generate the model file.
This new feature changes up my workflow slightly, perhaps for the better. For the times when you don’t want a migration file, you can use --skip-migration. For example:

$ script/generate model account --skip-migration

Ruby Is the Schema

In an about-face on defaults, database schemas are now dumped to the portable Ruby format using Active Record’s schema dumper rather than raw SQL. Which means if you run

$ rake db:test:clone

you’ll discover a db/schema.rb file which represents the schema used to load up the test database. You won’t find the db/development_structure.sql file that was created in Rails 1.0. Of course you can always go back to SQL by setting the following in your config/environment.rb file:

config.active_record.schema_format = :sql

Reloading Classes

If you want Rails to reload a model that isn’t a subclass of ActiveRecord::Base, you used to add the following declaration in a controller:

model :my_model

That syntax is now deprecated in favor of adding the following declaration in your model file:

include Reloadable

More In the Console

I use script/console from dawn to dusk, to and fro. How handy then that I can now leave it running as my app is changing and reload changes with reload! (say it with gusto!).

$ script/console
>> p = Product.find(1)
# go change the definition of Product

>> reload!
Reloading...
=> [ApplicationController, Product]

>> p = Product.find(1)
# call new methods on 'p'

As well, you can now call helper methods from the console. This turns out to be quite handy for learning, experimenting, playing:

$ script/console
>> helper.time_ago_in_words(Time.now)
=> "less than a minute"

>> helper.link_to 'Web 2.0', 'http://blink-tag.org'
=> "<a href=\"http://blink-tag.org\">Web 2.0</a>"

>> app.url_for :controller => 'store', :action => 'buy'
=> "http://www.example.com/store/buy"

FCGI Cleanup

In the old days (back about 24 hours ago), hitting CTRL-C on a Rails app running lighty wouldn’t consistently clean up all the FCGI processes. This had the insidious side effect of leaving a rogue process that you were sure to lock onto the next time you reloaded a page. Except that process had stale code. So you’d CTRL-C the app again to no avail. Some people reported that rebooting actually fixed the problem, which it did, but only because the process table was cleared.

Anyway, if you’ve ever fallen prey to this, you’ll be glad to know that Rails 1.1 cleans up FCGI processes nicely when you mash CTRL-C.

Thank you, to everyone who contributed to this release, for the big features in neon lights and the tiny fixes that make life a lot better. Now, back to building those apps…