编写数据库迁移以逆转复杂迁移

时间:2013-02-08 01:07:17

标签: ruby-on-rails migration rake

我的遗留应用程序中有一个非常旧的迁移,其中包含一个包含此代码段的朋友:

class MakeChangesToProductionDbToMatchWhatItShouldBe < ActiveRecord::Migration
  def self.up

# For some reason ActiveRecord::Base.connection.tables.sort().each blows up
    ['adjustments',
    'accounts',
     ...## more rows of classes here ###...
    'product_types'].each do |table|
      t = table.singularize.camelize.constantize.new
      if t.attributes.include?('created_at')
        change_column( table.to_sym, :created_at, :datetime,  :null => false ) rescue puts      "#{table} doesnt have created_at"
      end
      if t.attributes.include?('updated_at')
        change_column( table.to_sym, :updated_at, :datetime,  :null => false ) rescue puts "#{table} doesnt have updated_at"
      end
    end

这个旧的迁移现在与我为了删除这个长列表中提到的两个表而编写的新迁移相冲突,现在导致rake db:migrate上的任何部署都出错。

为解决此迁移而编写的正确迁移或停止操作是什么样的,并使db:migrate再次运行?

1 个答案:

答案 0 :(得分:2)

有一些不同的最佳实践可以帮助,但是在一天结束时,没有好的方法可以始终从任意点升级数据库,而无需在运行时逐步执行代码库迁移(说到哪,为什么还没有执行此任务的rake任务?)。

  1. 始终包含您正在处理的模型的迁移命名空间副本。以下示例。
  2. 从头开始构建数据库时,执行 not 运行迁移...使用db:schema:load将重新创建数据库的最后一个快照。
  3. 不要让你的移民像MakeChangesToProductionDbToMatchWhatItShouldBe那样荒谬而具有侵略性的标题。
  4. 在编写迁移时,避免假设它们将运行的环境。这包括指定表名,数据库驱动程序,环境变量等。
  5. 当您执行向下操作时,在写入操作时记下操作。当一系列变换在你脑海中浮现时,通常会更容易(特别是在深奥或复杂的迁移中)。
  6. 对于这种特定情况,有一个论点要求声明“迁移破产” - 清除部分或全部现有迁移(或重构和合并到新的迁移)以实现所需的数据库状态。当你这样做你不再向后兼容所以不能掉以轻心,但有时候这是适当的举动。