如何回滚失败的Rails迁移?我希望这rake db:rollback会撤消失败的迁移,但是不,它会回滚以前的迁移(失败的迁移减去一个)。而且rake db:migrate:down VERSION=myfailedmigration也不起作用。我已经遇到过几次了,这非常令人沮丧。这是我做的一个简单测试,可以重复该问题:
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:迁移============================================= ======== -add_column(:assets,:test,:integer) -> 0.0932秒 -add_column(:asset,:error) 耙子流产了! 发生错误,所有后来的迁移都被取消: 错误的参数数量(2对3)
好的,让我们回滚一下:
$ rake db:rollback == AddLevelsToRoles:还原============================================ == -remove_column(:roles,:level) -> 0.0778秒 == AddLevelsToRoles:恢复(0.0779s)=====================================
嗯?那是我在SimpleTest之前的最后一次迁移,而不是失败的迁移。(哦,如果迁移输出中包含版本号,那就太好了。)
因此,让我们尝试为失败的迁移SimpleTest运行失败:
$ rake db:migrate:down VERSION = 20090326173033 $
什么也没发生,也没有输出。但是也许它还是进行了迁移吗?因此,让我们修复SimpleTest迁移中的语法错误,然后尝试再次运行它。
$ rake db:migrate:up VERSION = 20090326173033 == SimpleTest:迁移============================================= ======== -add_column(:assets,:test,:integer) 耙子流产了! Mysql :: Error:重复的列名'test':ALTER TABLE`assets` ADD`test` int(11)
不。显然,migrate:down无效。这不是失败,只是没有执行。
除了手动进入数据库并删除它,然后运行测试之外,没有办法摆脱重复的表。有比这更好的方法。
不幸的是,您必须手动清理失败的MySQL迁移。MySQL不支持事务数据库定义更改。
Rails 2.2包括针对PostgreSQL的事务迁移。Rails 2.3包括SQLite的事务迁移。
这现在并不能真正解决您的问题,但是,如果您可以在将来的项目中选择数据库,我建议您使用支持事务性DDL的数据库,因为它使迁移更加轻松。
更新-在2017年的Rails 4.2.7和MySQL 5.7上仍然如此,这是Alejandro Babio在另一个答案中报告的。