问题
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.
回答1:
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.
回答2:
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
来源:https://stackoverflow.com/questions/24520550/how-do-you-make-remove-column-reversible