Josh Lane Code that I felt like sharing

Automatic database migration for happiness

So I find this little bastard in Rails ~> 4.0.0 wicked annoying.

ActiveRecord::Migration.check_pending!

Except, I get it. It’s not up to Rails to decide if you want run your migrations or not.

Sometimes you are working on tests, and you have a pending migration but you don’t want it to run yet. What I do dislike is checking out some updates, running tests and then immediately failing. DataMapper is especially anal about this because of the relationship integrity checks.

My solution is to sprinkle this little snippet around:

Rails.application.config.after_initialize do
  needs_migration = begin
                      ActiveRecord::Migrator.needs_migration?(ActiveRecord::Base.connection)
                    rescue ActiveRecord::NoDatabaseError
                      true
                    end
  # migrate database if migration file isn't run but is in version control
  pending_migration = (Dir["db/migrate/*.rb"] - `git ls-files db/migrate/*.rb`.split($\)).empty?

  if !ENV["NO_MIGRATE"] && %w[development test].include?(Rails.env) &&
      needs_migration && pending_migration
    ActiveRecord::Tasks::DatabaseTasks.create_current
    ActiveRecord::Migrator.up(ActiveRecord::Tasks::DatabaseTasks.migrations_paths)
  end
end

The real clutch piece here is that having a migration checked into git effectively means it’s ready for party time.

The gating of the development and test environment is important because you probably don’t want your database migrations to run as a side effect of booting your app in production.

I usually stuff this in config/application.rb but you could just as easily but it in a config/initializer/auto_migrate.rb file.

Happy auto migrating!