Ruby on rails Rails:进行不可逆转的迁移是否不好?

Ruby on rails Rails:进行不可逆转的迁移是否不好?,ruby-on-rails,migration,Ruby On Rails,Migration,何时可以在迁移的self.down方法中引发ActiveRecord::不可逆转迁移异常?您应该在什么时候真正实施反向迁移?IIRC,在迁移过程中更改数据类型时,您将进行不可逆迁移。感觉需要不可逆迁移可能是您面临更大问题的迹象。也许一些细节会有帮助 至于你的第二个问题:我总是“努力”写迁移的反面。当然,我实际上并没有写.down,TextMate在创建.up时会自动插入.down,如果您处理的是生产级系统,那么是的,这非常糟糕。如果这是您自己的宠物项目,那么任何事情都是允许的(如果没有其他事情,

何时可以在迁移的self.down方法中引发ActiveRecord::不可逆转迁移异常?您应该在什么时候真正实施反向迁移?

IIRC,在迁移过程中更改数据类型时,您将进行不可逆迁移。

感觉需要不可逆迁移可能是您面临更大问题的迹象。也许一些细节会有帮助


至于你的第二个问题:我总是“努力”写迁移的反面。当然,我实际上并没有写
.down
,TextMate在创建
.up
时会自动插入
.down
,如果您处理的是生产级系统
,那么是的,这非常糟糕。如果这是您自己的宠物项目,那么任何事情都是允许的(如果没有其他事情,这将是一次学习经验:),尽管很可能是早晚,即使是在宠物项目中,您也会发现自己已经跨越了反向迁移,只需在几天后撤销该迁移,无论是通过
rake
还是手动操作。)

在生产场景中,您应该始终努力编写和测试可逆迁移,以防在生产过程中遇到这种情况,然后发现一个错误,迫使您回滚(代码和模式)到以前的某个版本(等待一些非平凡的修复——以及其他不可用的生产系统)

反向迁移的范围从最简单的(删除迁移过程中添加的列或表,和/或更改列类型等)到更复杂的(
execute
of
JOIN
ed
INSERT
s或
UPDATE
s),但没有什么比这更复杂的事情可以证明“将其隐藏起来”。如果没有别的,强迫自己思考实现反向迁移的方法可以让您对正向迁移正在解决的问题有新的认识

您可能偶尔会遇到这样的情况:正向迁移会删除某个功能,从而导致从数据库中丢弃数据由于明显的原因,反向迁移无法恢复被丢弃的数据。尽管在这种情况下,可以建议让正向迁移自动保存数据,或在可能发生回滚时保留数据,以替代彻底失败(保存到
yml
,复制/移动到特殊表等),您不必这样做,因为测试这种自动化过程所需的时间可能会超过手动恢复数据所需的时间(如果需要)。但即使在这种情况下,您也可以有条件地进行反向迁移,并在等待某些用户操作之前暂时失败(即,测试是否存在需要手动还原的某些表;如果缺少,则输出“我失败,因为我无法从虚无中重新创建表
XYZ
;从备份中手动还原表
XYZ
,然后再次运行我,我不会让您失败!”)

在生产场景中,您应该始终努力编写和测试可逆迁移,以防在生产中遇到这种情况,然后发现一个错误,迫使您回滚(代码和模式)到以前的某个版本(等待一些非平凡的修复——以及一个不可用的生产系统)


可逆迁移对于开发和登台来说很好,但假设经过良好测试的代码,您希望在生产中向下迁移的情况应该非常罕见。我在迁移中构建了一个生产模式下的自动不可逆迁移。如果我真的需要逆转更改,我可以使用另一个“向上”迁移迁移或删除异常。这看起来很粗略。任何可能导致这种可怕情况的错误都表明QA过程严重出错。

如果要销毁数据,可以先对其进行备份。 e、 g

使用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
class RemoveStateFromProductproduct.state}
结束
备份数据
删除列:产品,:状态
结束
def自动关闭
添加列:产品,:状态,:字符串
恢复产品
结束
结束

我认为另一种可行的情况是合并迁移。在这种情况下,“down”实际上没有意义,因为它会删除所有表(除了合并后添加的表)。这可能不是您想要的。

一旦您进行了几十次或数百次迁移,也值得向上抛出一个异常,大意是“这是不可逆的。您确定吗?”在运行迁移之前,您可以使用来保存数据库的完整状态。如果您需要恢复迁移,甚至在迁移实际丢弃数据的情况下,您也可以这样做。您还可以使用它来测试迁移。或者公司太小,没有好的QA流程,或者经理不支持它。有一件事我们需要解决通常认为生产和暂存的区别在于:数据库的内容。因此,QA最有可能无法跟踪的事情是迁移遇到了一个被忽略的情况。这也是可能出错的最严重的事情之一。谨慎似乎是合理的。
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