如何回滚一个失败的Rails迁移?我期望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: 进行迁移 ===================================================== -- 添加列(:assets, :test, :integer) -> 0.0932秒 -- 添加列(:asset, :error) rake中止! 发生错误,所有后续的迁移都被取消:
错误的参数数量 (2 for 3)
好的,让我们回滚:
$ rake db:rollback == AddLevelsToRoles: 正在还原 =============================================== -- 移除列(:roles, :level) -> 0.0778秒 == AddLevelsToRoles: 已还原 (0.0779秒) ======================================
嗯?这是我在SimpleTest之前执行的最后一次迁移,而不是失败的迁移。 (并且哦,如果迁移输出包含版本号会很好。)
所以让我们尝试运行失败的SimpleTest迁移的down命令:
$ rake db:migrate:down VERSION=20090326173033 $
没有任何反应,也没有输出。但也许它已经运行了迁移?因此让我们修复SimpleTest迁移中的语法错误,然后再尝试运行它。
$ rake db:migrate:up VERSION=20090326173033 == SimpleTest: 进行迁移 ===================================================== -- 添加列(:assets, :test, :integer) rake中止! Mysql::Error: Duplicate column name 'test': ALTER TABLE `assets` ADD `test` int(11)
不行。显然migrate:down命令没有生效。它没有失败,只是没有执行。
除了手动进入数据库删除该重复表并运行测试外,没有任何摆脱重复表的方法。肯定有更好的方法。