I have the following migration:
class AddMyColumn < ActiveRecord::Migration[6.1]
def change
add_column :my_table, :my_new_column, :bigint
add_foreign_key :my_table, :my_other_table, column: :my_new_column
add_index :my_table, :my_new_column
end
end
When reversing this migration, I see this error:
Mysql2::Error: Cannot drop index 'index_my_table_on_my_new_column': needed in a foreign key constraint
The Rails guide explicitly says that a change
migration using these actions should be reversible.
Re-ordering the add_foreign_key
and add_index
actions (or in this case, using add_reference
) allows the migration to reverse successfully. However, this seems to contradict the documentation that states:
Active Record knows how to reverse a migration's actions automatically... [when using] actions that
change
supports. If you're going to need to use any other methods, you should use reversible or write the up and down methods instead of using the change method
add_column
add_foreign_key
& add_index
are all supported actions.
Does the change
method perform any analysis of the actions in order to reverse them appropriately? Or does it simply apply them in the reverse order? Is this behavior documented anywhere?
Does the change method perform any analysis of the actions in order to reverse them appropriately?
There is a class that's responsible for reversing known methods:
https://api.rubyonrails.org/classes/ActiveRecord/Migration/CommandRecorder.html#method-i-inverse_of
Or does it simply apply them in the reverse order? Is this behavior documented anywhere?
Migration methods are executed from bottom up inside the change
method (which you can just see in the log).
https://api.rubyonrails.org/classes/ActiveRecord/Migration/CommandRecorder.html#method-i-revert
While executing the given block, the recorded will be in reverting mode. All commands recorded will end up being recorded reverted and in reverse order.