Rails has this cool feature called ActiveRecord Migration. It’s an easy way to create and update your database. But if you get it wrong it is super annoying. This is where migrations and me loathe each other.

I had a migration which had the wrong column names. Now I could easily create another migration to change the names, but I’m still developing and I don’t want yet another migration. First thing I did was modified the migration before rolling things back. That is definitely going to fail. SO I reverted my changes.

class AddRhevParams < ActiveRecord::Migration
  def change
    remove_column :fusor_deployments, :rhev_params
    add_column :fusor_deployments, :rhev_hypervisor_host_id, :integer
    add_column :fusor_deployments, :rhev_engine_host_id, :integer
    add_column :fusor_deployments, :rhev_hypervisor, :string
    add_column :fusor_deployments, :rhev_engine, :string
    add_column :fusor_deployments, :rhev_database, :string
    add_column :fusor_deployments, :rhev_cluster, :string
    add_column :fusor_deployments, :rhev_storage, :string
    add_column :fusor_deployments, :rhev_cpu, :string
    add_column :fusor_deployments, :rhev_share, :string
  end
end

First I tried rake db:rollback STEP=1 hoping that it would put the DB in the state prior to my latest migration. For whatever reason it failed with an IrreversableMigration error.

$ rake db:rollback STEP=1
The Apipie cache is turned off. Enable it and run apipie:cache rake task to speed up API calls.
Workaround for RbVmomi may not work as ComputeResource is already loaded: ComputeResource
[deprecated] I18n.enforce_available_locales will default to true in the future. If you really want to skip validation of your locale you can set I18n.enforce_available_locales = fal
se to avoid this message.
==  AddRhevParams: reverting ==================================================
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:

ActiveRecord::IrreversibleMigration/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration/command_recorder.rb:42:in `block in inverse'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration/command_recorder.rb:40:in `map'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration/command_recorder.rb:40:in `inverse'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:401:in `block (3 levels) in migrate'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:358:in `revert'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:400:in `block (2 levels) in migrate'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:399:in `block in migrate'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/connection_adapters/abstract/connection_pool.rb:129:in `with_connection'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:389:in `migrate'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:528:in `migrate'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:720:in `block (2 levels) in migrate'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:775:in `call'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:775:in `block in ddl_transaction'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/connection_adapters/abstract/database_statements.rb:192:in `transaction'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/transactions.rb:208:in `transaction'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:775:in `ddl_transaction'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:719:in `block in migrate'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:700:in `each'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:700:in `migrate'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:574:in `down'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:656:in `move'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:562:in `rollback'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/railties/databases.rake:276:in `block (2 levels) in '
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/bin/ruby_executable_hooks:15:in `eval'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/bin/ruby_executable_hooks:15:in `'
caused by: (ActiveRecord::IrreversibleMigration) ActiveRecord::IrreversibleMigration
    ... skipped 46 lines
ActiveRecord::IrreversibleMigration: ActiveRecord::IrreversibleMigration
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration/command_recorder.rb:42:in `block in inverse'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration/command_recorder.rb:40:in `map'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration/command_recorder.rb:40:in `inverse'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:401:in `block (3 levels) in migrate'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:358:in `revert'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:400:in `block (2 levels) in migrate'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:399:in `block in migrate'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/connection_adapters/abstract/connection_pool.rb:129:in `with_connection'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:389:in `migrate'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:528:in `migrate'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:720:in `block (2 levels) in migrate'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:775:in `call'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:775:in `block in ddl_transaction'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/connection_adapters/abstract/database_statements.rb:192:in `transaction'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/transactions.rb:208:in `transaction'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:775:in `ddl_transaction'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:719:in `block in migrate'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:700:in `each'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:700:in `migrate'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:574:in `down'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:656:in `move'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:562:in `rollback'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/railties/databases.rake:276:in `block (2 levels) in '
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/bin/ruby_executable_hooks:15:in `eval'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/bin/ruby_executable_hooks:15:in `'
Tasks: TOP => db:rollback
(See full trace by running task with --trace)

Then I tried rake db:migrate:down --trace VERSION= and that failed with the same error.

$ rake db:migrate:down --trace VERSION=20150216190947
** Invoke db:migrate:down (first_time)
** Invoke environment (first_time)
** Execute environment
The Apipie cache is turned off. Enable it and run apipie:cache rake task to speed up API calls.
Workaround for RbVmomi may not work as ComputeResource is already loaded: ComputeResource
[deprecated] I18n.enforce_available_locales will default to true in the future. If you really want to skip validation of your locale you can set I18n.enforce_available_locales = fal
se to avoid this message.
** Invoke db:load_config (first_time)
** Execute db:load_config
** Execute db:migrate:down
==  AddRhevParams: reverting ==================================================
rake aborted!
ActiveRecord::IrreversibleMigration: ActiveRecord::IrreversibleMigration
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration/command_recorder.rb:42:in `block in inverse'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration/command_recorder.rb:40:in `map'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration/command_recorder.rb:40:in `inverse'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:401:in `block (3 levels) in migrate'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:358:in `revert'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:400:in `block (2 levels) in migrate'
/home/vagrant/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/benchmark.rb:280:in `measure'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:399:in `block in migrate'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/connection_adapters/abstract/connection_pool.rb:129:in `with_connection'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:389:in `migrate'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:528:in `migrate'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:679:in `run'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/migration.rb:578:in `run'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.21/lib/active_record/railties/databases.rake:238:in `block (3 levels) in '
/home/vagrant/.rvm/gems/ruby-1.9.3-p448@global/gems/rake-10.4.2/lib/rake/task.rb:240:in `call'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448@global/gems/rake-10.4.2/lib/rake/task.rb:240:in `block in execute'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448@global/gems/rake-10.4.2/lib/rake/task.rb:235:in `each'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448@global/gems/rake-10.4.2/lib/rake/task.rb:235:in `execute'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448@global/gems/rake-10.4.2/lib/rake/task.rb:179:in `block in invoke_with_call_chain'
/home/vagrant/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/monitor.rb:211:in `mon_synchronize'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448@global/gems/rake-10.4.2/lib/rake/task.rb:172:in `invoke_with_call_chain'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448@global/gems/rake-10.4.2/lib/rake/task.rb:165:in `invoke'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448@global/gems/rake-10.4.2/lib/rake/application.rb:150:in `invoke_task'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448@global/gems/rake-10.4.2/lib/rake/application.rb:106:in `block (2 levels) in top_level'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448@global/gems/rake-10.4.2/lib/rake/application.rb:106:in `each'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448@global/gems/rake-10.4.2/lib/rake/application.rb:106:in `block in top_level'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448@global/gems/rake-10.4.2/lib/rake/application.rb:115:in `run_with_threads'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448@global/gems/rake-10.4.2/lib/rake/application.rb:100:in `top_level'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448@global/gems/rake-10.4.2/lib/rake/application.rb:78:in `block in run'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448@global/gems/rake-10.4.2/lib/rake/application.rb:176:in `standard_exception_handling'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448@global/gems/rake-10.4.2/lib/rake/application.rb:75:in `run'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448@global/gems/rake-10.4.2/bin/rake:33:in `'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448@global/bin/rake:19:in `load'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448@global/bin/rake:19:in `'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/bin/ruby_executable_hooks:15:in `eval'
/home/vagrant/.rvm/gems/ruby-1.9.3-p448/bin/ruby_executable_hooks:15:in `'
Tasks: TOP => db:migrate:down

Doing some googling, I found you can run rails console and run the migrations by hand, see Executing Migration Commands From Rails Console.

I then ran these commands in my rails console:

ActiveRecord::Migration.remove_column :fusor_deployments, :rhev_hypervisor_host_id
ActiveRecord::Migration.remove_column :fusor_deployments, :rhev_engine_host_id
ActiveRecord::Migration.remove_column :fusor_deployments, :rhev_hypervisor
ActiveRecord::Migration.remove_column :fusor_deployments, :rhev_engine
ActiveRecord::Migration.remove_column :fusor_deployments, :rhev_database
ActiveRecord::Migration.remove_column :fusor_deployments, :rhev_cluster
ActiveRecord::Migration.remove_column :fusor_deployments, :rhev_storage
ActiveRecord::Migration.remove_column :fusor_deployments, :rhev_cpu
ActiveRecord::Migration.remove_column :fusor_deployments, :rhev_share
ActiveRecord::Migration.add_column :fusor_deployments, :rhev_params, :text

Then I went into the database and deleted the reference to my migration from the schema_migrations.

=# delete from schema_migrations where version = '20150216190947';

That cleaned up the migration and I was able to rerun using rake db:migrate

class AddRhevParams < ActiveRecord::Migration
  def change
    remove_column :fusor_deployments, :rhev_params
    add_column :fusor_deployments, :rhev_hypervisor_host_id, :integer
    add_column :fusor_deployments, :rhev_engine_host_id, :integer
    add_column :fusor_deployments, :rhev_hypervisor_hostname, :string
    add_column :fusor_deployments, :rhev_engine_hostname, :string
    add_column :fusor_deployments, :rhev_database_name, :string
    add_column :fusor_deployments, :rhev_cluster_name, :string
    add_column :fusor_deployments, :rhev_storage_name, :string
    add_column :fusor_deployments, :rhev_storage_type, :string
    add_column :fusor_deployments, :rhev_storage_address, :string
    add_column :fusor_deployments, :rhev_cpu_type, :string
    add_column :fusor_deployments, :rhev_share_path, :string
  end
end

So if you have trouble rolling things back automatically, you can try using rails console and mucking with the schema_migrations database table.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s