Sunday, July 06, 2008

How to: Avoid getting your database wiped when migrating to rails 2.1

We recently migrated some projects from rails 1.2 to 2.1.

In doing this, we encountered a bug where sometimes (in production only) running rake db:migrate goes wrong, and re-runs all your migrations

The unhappy side effect of it re-running ALL the migrations, is that it effectively re-creates your entire database, and you lose all your data. USEFUL

I didn't have the time or the luxury to figure out quite why this was happening, if anyone does, please comment and let me know what it was. Apparently there's been a few other blogs mentioning it, but I don't have any of them at hand.

The workaround is to manually create the schema_migrations table before you run rake db:migrate in rails 2.1.

If you put the following script in your RAILS_ROOT/db directory, and run it, it will do that.

Enjoy. (Disclaimer: if there's a bug in the script, and it does anything awful, it's not my fault! You have been warned!)

require File.dirname(__FILE__) + '/../config/environment'

# Define some models
class SchemaInfo < ActiveRecord::Base
  set_table_name 'schema_info'
end
class SchemaMigration < ActiveRecord::Base; end

# Create the schema_migrations table
ActiveRecord::Migration.class_eval do
  create_table 'schema_migrations', :id => false do |t|
    t.column :version, :string, :null => false
  end
end

# Work out the migrated version and populate the migrations table

v = SchemaInfo.find(:first).version.to_i
puts "Current schema version is #{v}"
raise "Version number doesn't seem right!" if v == 0

1.upto(v) do |i|
 SchemaMigration.create!( :version => i )
 puts "Added entry for migration #{i}"
end

# Drop the schema info table, as rails-2.1 won't automatically do it thanks to our hacking
ActiveRecord::Migration.class_eval do
  drop_table 'schema_info'
end

No comments: