Tuesday, March 14, 2006

R-Rails Gets R-Recognized

image


No, I’m not stuttering. This evening, at the Software Development Jolt Awards at SD West in Santa Clara, Agile Web Development with Rails received the Jolt Award for best technical book, and Rails 1.0 won the Jolt for best web development tools.


I have to say, when I saw that both the book and the framework were up for awards, I was nervous, thinking that the judges might not want to vote for Rails in two separate categories. The fact that they did says a lot for the way Rails is now a mainstream player in the enterprise software world. It’s clear the tipping point is behind us now, and we’re a player.


Congratulations to DHH on his Jolt. And congratulations to the Pragmatic Bookshelf: this is our second Jolt Award in three years.


And, mostly, thanks to the Ruby community for providing the environment in which all this can happen. I’m really proud of us all.

Sunday, February 26, 2006

Annotate Models Plugin

Rails model files contain no information on the tables they represent. This is a good thing in general, because it reduces duplication—add a column to a table, and there’s no configuration to update in the model.


However, when you’re writing code, it’s sometimes nice to be able to see just what attributes a model has.


Enter annotate models, a really trivial Rails plugin I hacked up in the plane back from the first No Fluffof the year. The plugin adds a comment block to the top of each model file, documenting the schema. If you update the schema, run it again and it updates the comment.


  # Schema as of Mon Feb 27 00:55:58 CST 2006 (schema version 7)
#
# id :integer(11) not null
# name :string(255)
# description :text
# image_location :string(255)
# price :float default(0.0)
# available_at :datetime
#

class Product < ActiveRecord::Base

validates_presence_of :name, :description
. . .

Install using:


  > script/plugin install http://repo.pragprog.com/svn/Public/plugins/annotate_models

and run with:


  > rake annotate_models

It only handles models directly under app/models. And, as it’s new, you’d be advised to back up your model files before running it.

Monday, February 6, 2006

Rails Guidebook is Full

I’m blown away!




The Rails Guidebook, our day of pre-conference training before RailsConf, is now officially full. Chad Fowler and Jay Zimmerman, who are handling logistics, twice negotiated to get bigger rooms, but we’ve had to draw the line at 150.


Yes, 150!


One hundred and fifty people are coming to learn about Rails, and have agreed to donate at least $40 to charity. Many folks have already donated a lot more. (And, remember, the three biggest donations get some VIP treatment.) I’m so, so proud of our community for making this happen. Ruby folks have always been nice to be around. To see them contributing back to the outside world like this just confirms it.


Thank you all.


(If you are coming, remember to get your donation in, and bring your receipt. See you there.)



Sunday, February 5, 2006

RailsConf and the Rails Guidebook

RailsConf in Chicago (June 22-25) promises to be an exciting affair. And it looks as if there’ll be a number of people coming who are fairly new to Rails.


So Mike and Nicole Clark and I were sitting down after a day of teaching a Rails Studio, and we came up with an idea. We’ll be running a one-day course before the conference. It is designed to bring newcomers to Rails up to speed, both with the framework and with Ruby.


We’re calling it the Rails Guidebook. Think of it as the difference between between turning up somewhere exotic knowing nothing about the language, customs, and places to visit, and turning up having spent a small amount of time reading a guide book. Hopefully, a day spent with us will make the rest of the conference more enjoyable (and informative).


We’re not charging for the Guidebook—it’s our way of saying “thank you” to the community. Instead, we’re asking folks to donate to charity before they come. Space is limited, so you might want to book early. (And, the top 3 contributors will get some perks…)

Friday, January 27, 2006

Link:

Andy and I have had to cut back on conferences this year, but it looks like we’re making an exception for this one.

Tuesday, January 3, 2006

Sharing External ActiveRecord Connections

I had a problem with a deployed Rails application today that Mike Clark helped me track down.


It started after Mike and I migrated a Rails app to a new, zippier server. Everything looked great (and the app ran a lot faster). However, after a while, I started getting problems with a database. To explain what went wrong, I need to chat a little about the application.


This piece of code is an attempt to migrate functionality away from a particularly nasty set of old CGIs, web applications, bailing wire, chewing gum, and other historical crud. There’s a lot of existing functionality, and I decided not to try to port it all across to Rails on day one. Instead, I gave the Rails application its own database to play with, and gave it access to the old legacy database for when it needed to look up stuff in the existing system. To do that, I created a set of ActiveRecord classes for the legacy tables, and explicitly connected them to the legacy database, rather than the default Rails application database. A typical legacy model class looked smething like this:


  class LegacyOrder < ActiveRecord::Base
set_table_name "orders"
set_primary_key "o_id"

establish_connection "legacy_#{RAILS_ENV}"
...
end

(The ”legacy_#{RAILS_ENV}” stuff lets me have development, test, and production versions of the legacy database in my database.yml file.)


So far, so good. I had four different legacy tables I mapped this way, and everything worked fine.


However, after a while, other applications accessing the legacy database started failing, claiming they couldn’t connect. Sure enough, it turned out that there were hundreds of active connections to that database: the database wasn’t going to accept any more.


The problem was that I was creating way too many connections to the legacy database. Each spawned Rails fcgi process established a separate connection to the legacy database for each legacy ActiveRecord class. That factor of four killed us.


But fixing it also raised an interesting question: in my original code, I established a separate connection for each legacy table in each running Rails process. This was clearly dumb. But what’s the best way of sharing a single connection between all of the legacy model objects in a Rails instance?


Some chatting on #rails-core came up wih three suggestions:


  1. Create the connection once (perhaps in one of the environment files), and then assign it to each of the legacy AR classes:
      legacy_connection = ActiveRecord::Base.mysql_connection(...)

    LegacyOrder.connection = legacy_connection
    LegacyLineItem.connection = legacy_connection
    ...


  2. Establish the connection in one model, then use it in the others
     class LegacyOrder < ActiveRecord::Base
    establish_connection ...
    end

    class LegacyLineItem < ActiveRecord::Base
    connection = LegacyOrder.connection
    end


  3. Somehow make all the legacy models share a common parent, and have that parent own the connection.

Options (1) and (2) seemed messy: they added a bunch of coupling to the code where it wasn’t really justified. Option (3) seemed like the way to go. The only problem was that no one on #rails-core was sure it would work…


It turns out it does.


  class LegacyBase < ActiveRecord::Base
establish_connection ...
end

class LegacyOrder < LegacyBase
...
end

class LegacyLineItem < LegacyBase
...
end

The parent class creates a single connection to the legacy database, and all the child classes share it. The reason it works is some smarts in Rails.


It turns out that Rails does just about everything lazily. That includes connecting to databases and reflecting on tables to extract the schema (needed to build the internals of the models). This improves performance, but it also makes this hack possible. In general, you’d expect the LegacyBase class to map to a database table called legacy_base. It would, if we ever tried to use it to access data. But because we don’t, and because Rails only reflects on the table the first time a data access occurs, we can safely create an ActiveRecord class with no underlying database table.


This scheme lets me specify the legacy connection once, and share that connection between all my legacy models. It’s tidy, expressive, and saves resources.

Monday, January 2, 2006

The Water Fountain Methodology

From a Rails irc channel (htonl is Scott Barron)…


htonl:  yeah we’ve canned agility here
htonl:  we’re doing the water fountain technique 
htonl:  we mostly just spew code up in an arch and it falls down the drain