How do you make remove_column reversible?

Ruby on-RailsRails Migrations

Ruby on-Rails Problem Overview


I have a migration that removes a column:

def change
  remove_column :foos, :bar, :boolean
end

When I try to rake db:rollback that migration, I get the following error:

remove_column is only reversible if given a type.

The ActiveRecord::Migration documentation says that the following is the signature for remove_column:

remove_column(table_name, column_name, type, options)

So my type in this case should be :boolean, and I expect that migration to be reversible. What am I missing?

I can certainly break this out into an up and down migration to avoid this problem, but I'd like to understand why the change syntax isn't working in this case.

Ruby on-Rails Solutions


Solution 1 - Ruby on-Rails

Simply adding the 3rd argument (the column's :type) to the remove_column method makes that migration reversible. So the OP's original code actually did work, as in:

remove_column :foos, :bar, :boolean

The rest of this answer was an attempt to discover why this method would not have been working, but the OP ended up getting it to work.


I see somewhat contrary info in the documentation for ActiveRecord::Migration:

> Some commands like remove_column cannot be reversed. If you care to define how to move up and down in these cases, you should define the up and down methods as before. > > For a list of commands that are reversible, please see ActiveRecord::Migration::CommandRecorder.

And this from ActiveRecord::Migration::CommandRecorder:

> ActiveRecord::Migration::CommandRecorder records commands done during a migration and knows how to reverse those commands. The CommandRecorder knows how to invert the following commands: > > add_column > > add_index > > add_timestamps > > create_table > > create_join_table > > remove_timestamps > > rename_column > > rename_index > > rename_table

Anyway, it appears that this documentation is out of date... Digging into the source on github:

The method that's giving you grief is:

def invert_remove_column(args)
  raise ActiveRecord::IrreversibleMigration, "remove_column is only reversible if given a type." if args.size <= 2
  super
end

I gave this a shot... setup a migration on my Rails 4.1.2 app and the migration worked both ways -- up and down. Here was my migration:

class TestRemoveColumn < ActiveRecord::Migration
  def change
    remove_column :contacts, :test, :boolean
  end
end

I also tried with the :boolean argument missing and got the same error as you're talking about. Are you sure you're on the final version of Rails 4.1.2 -- not one of the release candidates? If you are, I'd suggest putting a binding.pry into the Rails source for the invert_remove_column method to inspect the arguments list and see what's going on. To do so, just run bundle open activerecord and then explore to: lib/active_record/migration/command_recorder.rb:128.

Solution 2 - Ruby on-Rails

Instead of using change, you use up and down methods to your migration:

def up
  remove_column :foos, :bar
end

def down
  add_column :foos, :bar, :boolean
end

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser1454117View Question on Stackoverflow
Solution 1 - Ruby on-RailspdobbView Answer on Stackoverflow
Solution 2 - Ruby on-RailsbratscheView Answer on Stackoverflow