in Rails, Ruby

Checking for Model Classes Before Using Them in Rails Migrations

If you are using model objects in migrations (e.g. for inserting data) you should make sure that the migration works even if that model class is removed. I discovered this when setting up a new development environment and running all migrations in an empty database.

Let’s say you have the following migration code:

[source:ruby]
class InsertCounties < ActiveRecord::Migration def self.up County.create :code => ’10’, :name => ‘Blekinge’
County.create :code => ’20’, :name => ‘Dalarna’
end
end
[/source]

This assumes that the County model is available when the migration is run. If you checked out the most recent version of your code from svn it is possible that it doesn’t contain the County model and the migration will fail. To check if County is available before trying to use it we can use Ruby’s defined? like this:

Update: No we can’t. defined? always returns false inside an ActiveRecord migration for some reason (maybe the class isn’t loaded before the actual call?). We have to use a begin…rescue…end block instead:

[source:ruby]
class InsertCounties < ActiveRecord::Migration def self.up begin County.create :code => ’10’, :name => ‘Blekinge’
County.create :code => ’20’, :name => ‘Dalarna’
rescue
puts “Could not add data…”
end
end
end
[/source]

This way the rest of the migrations will run.

Write a Comment here on the real web

Comment

  1. I understand this but wasn’t Migrations supposed to run in order? I mean, even if the database is empty it means that in some point it will reach the creation of the Countries tables (say, in migration number 010) and this data loading would take place necessarily after that (say, in migration number 021). This checking would necessary if you want to run the migrations out of order, but this defies the whole purpose of the schema_info versioning control, doesn’t it?

  2. Akita: Migrations run in order but if you use model classes a migration may depend on a specific version of the code tree. When I wanted to set up a new development environment I got the latest source code. The latest source code didn’t include the County model (it had been scrapped earlier). The tables were created properly in migration 009, County inserts in 010 and the data and table were removed in migration 015.

  3. Interesting topic you raised there. As far as I know though, the creators of Rails strongly suggest not using migrations to configure an empty database for an application — use the generated schema.rb instead. This avoids any problems with moving through migration steps with non-existent models and, what’s more important, works times faster.

    Migrations are useful when there’s an application running and you need to catch up with the development changes without losing any data. In this case you most probably won’t face the problem with missing models.

    Thanks for the articles. The one with the Hpricot buffer size is a real healer.