Tuesday, April 10, 2007

Rails: Use Ruby Schema syntax without using Migrations

I've touched on this topic a few times. I previously listed the pains of using Migrations. And, in my last post I gave an example of our solution. But, I never went further into why we made the choice.

For my current team, the choice was a fairly easy one. It's a large team and we were churning out migrations very quickly. Of course, the numbering became an issue, but keeping a consistent view of the database became a larger issue. There was no one place to get a clear view of what the table looked like (in code).

Another issue with Migrations is that the self.down methods are never really tested. Sure, you might go down then up with each build, but do you test the application at every step down and up? Without running all the tests at each down, it's impossible to know that the self.down did exactly what you expected.

Also, how often do you need to step up or down? We found that we wanted to drop the entire db with each build to ensure that we didn't have any data dependencies. Therefore, going back a version or 2 never seemed valuable.

Most importantly, we were eventually going to need to generate SQL and send it to the database group. This meant that migrations were only ever going to be run by our team. And, if we needed a view of the database at any given date, we could just look in Subversion for that copy of our schema.

Given the above thoughts, we decided to create one schema file per release. The schema file uses the same syntax as migrations and even allows us to specify the schema version (very much like the idea of using one migration per release).
ActiveRecord::Schema.define(:version => 1) do

create_table :accounts, :force => true do |t|
t.column :first_name, :string
t.column :last_name, :string
t.column :username, :string
t.column :password, :string
t.column :email, :string
t.column :company, :string
end

...
end
And, in case you missed it in the previous post, the task to run it is very simple.
task :migrate => :environment do
ActiveRecord::Base.establish_connection(environment)
require File.dirname(__FILE__) + '/../../db/schema/release_1.rb'
end
Migrations are fantastic, but if you don't need them you shouldn't live with the overhead.
Post a Comment