【发布时间】:2010-10-11 21:33:39
【问题描述】:
何时可以在迁移的 self.down 方法中引发 ActiveRecord::IrreversibleMigration 异常?您应该在什么时候努力实际实施迁移的逆向操作?
【问题讨论】:
何时可以在迁移的 self.down 方法中引发 ActiveRecord::IrreversibleMigration 异常?您应该在什么时候努力实际实施迁移的逆向操作?
【问题讨论】:
如果您正在处理生产级系统,那么是的,这是非常糟糕的。如果这是您自己的宠物项目,那么任何事情都是允许的(如果没有别的,这将是一种学习体验 :) 尽管迟早,即使在宠物项目中,您也会发现自己已经跨越了反向迁移只是必须在几天后撤消该迁移,无论是通过rake还是手动。)
在生产场景中,您应该始终努力编写和测试可逆迁移,以防万一在生产环境中通过它,然后发现错误这会迫使您回滚(代码 和 架构)到某个先前的修订版(等待一些重要的修复——以及其他无法使用的生产系统。)
反向迁移的范围从大多数微不足道的(删除在迁移期间添加的列或表,和/或更改列类型等)到更复杂的(execute of JOINed INSERTs 或 @987654326 @s),但没有什么比“把它扫到地毯下”更复杂的了。如果不出意外,强迫自己思考实现反向迁移的方法可以让您对正向迁移正在解决的问题有新的认识。
您可能偶尔会遇到向前迁移删除某个功能的情况,从而导致数据从数据库中被丢弃。 出于显而易见的原因,反向迁移无法恢复丢弃的数据。尽管在这种情况下,我们可以建议让正向迁移自动保存数据或在可能发生回滚时将其保留作为彻底的替代方案失败(保存到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。如果我真的需要撤消更改,我可以使用另一个“向上”迁移或删除异常。不过,这似乎很粗略。任何会导致这种可怕情况的错误都表明 QA 流程被严重搞砸了。
【讨论】:
感觉您需要进行不可逆转的迁移,这可能表明您遇到了更大的问题。也许一些细节会有所帮助?
至于你的第二个问题:我总是“努力”写迁移的逆向。当然,我实际上并没有写.down,TextMate在创建.up时会自动插入。
【讨论】:
Reversible Data Migration 使用 yaml 文件可以轻松创建可逆的数据迁移。
class RemoveStateFromProduct < ActiveRecord::Migration
def self.up
backup_data = []
Product.all.each do |product|
backup_data << {:id => product.id, :state => product.state}
end
backup backup_data
remove_column :products, :state
end
def self.down
add_column :products, :state, :string
restore Product
end
end
【讨论】:
IIRC,在迁移中更改数据类型时,您将拥有 IrreversibleMigration。
【讨论】:
我认为另一种可以的情况是您进行合并迁移时。在这种情况下,“向下”实际上没有意义,因为它会删除所有表(合并后添加的表除外)。这可能不是你想要的。
【讨论】: