何时可以在迁移的self.down方法中引发ActiveRecord :: IrreversibleMigration异常?您何时应该努力实际实现迁移的逆转?
如果您正在处理生产级系统,那么是的,这是非常糟糕的.如果这是你自己的宠物项目,那么任何事情都是允许的(如果没有别的话,这将是一次学习经历:)尽管很快就会有机会,即使在宠物项目中,你会发现自己已经跨越了反向迁移只需要在几天后撤消该迁移,无论是通过rake
还是手动.)
在生产场景中,您应该始终努力编写和测试可逆迁移,以便在生产过程中进行可逆迁移,然后发现一个错误,该错误会迫使您回滚(代码和架构)到之前的某个版本(待定)一些非平凡的修复 - 以及其他无法使用的生产系统.)
反向迁移范围从大多琐碎(删除列或迁移过程中添加的表,和/或改变列类型等),以稍微复杂(execute
的JOIN
ED INSERT
S或UPDATE
多个),但没有什么是如此复杂,足以支持"扫它在地毯下".如果不出意外,强迫自己想办法实现反向迁移可以让您对正向迁移正在修复的问题有新的认识.
您可能偶尔会遇到正向迁移删除功能的情况,导致数据从数据库中丢弃. 出于显而易见的原因,反向迁移无法使丢弃的数据复苏. 虽然在这种情况下,可以建议让正向迁移自动保存数据,或者在回滚的情况下保留数据,作为彻底失败的替代方法(保存到yml
,复制/移动到特殊的桌子等),不得不这样,因为测试这样一个自动程序所需的时间可能会超过手动恢复数据所需的时间(如果需要的话). 但即使在这种情况下,您也可以进行反向迁移,而不仅仅是失败.有条件地和暂时的失败等待某些用户操作(即测试是否存在必须手动恢复的某些必需表;如果丢失,则输出"我失败了因为我无法XYZ
从虚无中重新创建表; XYZ
从备份手动恢复表然后再次运行我,我不会让你失望!")
如果要销毁数据,可以先备份数据.例如
def self.up # create a backup table before destroying data execute %Q[create table backup_users select * from users] remove_column :users, :timezone end def self.down add_column :users, :timezone, :string execute %Q[update users U left join backup_users B on (B.id=U.id) set U.timezone = B.timezone] execute %Q[drop table backup_users] end
在生产场景中,您应该始终努力编写和测试可逆迁移,以便在生产过程中进行可逆迁移,然后发现一个错误,该错误会迫使您回滚(代码和架构)到之前的某个版本(待定)一些非平凡的修复 - 以及其他无法使用的生产系统.)
具有可逆迁移对于开发和分段来说是好的,但是假设经过良好测试的代码,您应该极少想要在生产中向下迁移.我在迁移中构建了一个生产模式下的自动IrreversibleMigration.如果我真的需要撤消更改,我可以使用另一个"向上"迁移或删除异常.这看起来很粗略.任何会导致这种情况严重的错误都表明质量保证流程被严重搞砸了.