Как откатить неудачную миграцию рельсов? Я ожидаю, что rake db:rollback
отменит неудачную миграцию, но нет, она откатит предыдущую миграцию (неудачная миграция минус один). И rake db:migrate:down VERSION=myfailedmigration
тоже не работает. Я сталкивался с этим несколько раз, и это очень расстраивает. Вот простой тест, который я сделал, чтобы продублировать проблему:
class SimpleTest < ActiveRecord::Migration
def self.up
add_column :assets, :test, :integer
# the following syntax error will cause the migration to fail
add_column :asset, :test2, :integer
end
def self.down
remove_column :assets, :test
remove_column :assets, :test2
end
end
результат:
== SimpleTest: migrating =====================================================
-- add_column(:assets, :test, :integer)
-> 0.0932s
-- add_column(:asset, :error)
rake aborted!
An error has occurred, all later migrations canceled:
wrong number of arguments (2 for 3)
хорошо, давайте вернемся назад:
$ rake db:rollback
== AddLevelsToRoles: reverting ===============================================
-- remove_column(:roles, :level)
-> 0.0778s
== AddLevelsToRoles: reverted (0.0779s) ======================================
да? это была моя последняя миграция до SimpleTest, а не неудачная миграция. (И было бы неплохо, если бы вывод миграции включал номер версии.)
Итак, давайте попробуем запустить down для неудачной миграции SimpleTest:
$ rake db:migrate:down VERSION=20090326173033
$
Ничего не происходит и вывода тоже нет. Но, может быть, это все-таки запустило миграцию? Итак, давайте исправим синтаксическую ошибку в миграции SimpleTest и попробуем запустить ее снова.
$ rake db:migrate:up VERSION=20090326173033
== SimpleTest: migrating =====================================================
-- add_column(:assets, :test, :integer)
rake aborted!
Mysql::Error: Duplicate column name 'test': ALTER TABLE `assets` ADD `test` int(11)
Неа. Очевидно, что миграция: вниз не работает. Это не сбой, просто не выполняется.
Нет способа избавиться от этой дублированной таблицы, кроме как вручную войти в базу данных и удалить ее, а затем запустить тест. Должен быть лучший способ, чем это.