1

我的一个朋友在旧版应用程序上进行了相当古老的迁移,其中包含以下代码段:

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 再次工作而编写的正确迁移或关闭操作是什么?

4

1 回答 1

2

有一些不同的最佳实践可以提供帮助,但归根结底,没有什么好的方法可以在运行迁移时始终从任意点升级数据库而不单步执行代码库(说到这一点,为什么不已经是一项艰巨的任务了?)。

  1. 始终包含您正在处理的模型的迁移命名空间副本。下面的例子。
  2. 从头开始构建数据库时,不要运行迁移...使用db:schema:load它将重新创建数据库的最后一个快照。
  3. 不要给你的迁移带来荒谬和侵略性的标题,比如MakeChangesToProductionDbToMatchWhatItShouldBe.
  4. 在编写迁移时,避免对它们将在其中运行的环境做出假设。这包括指定表名、数据库驱动程序、环境变量等。
  5. 只要向下操作可行,就在您编写操作时写下操作。当一系列转换在您的脑海中浮现时,通常会容易得多(尤其是在深奥或复杂的迁移中)。

对于这种特定情况,有理由宣布“迁移破产”——清除部分或全部现有迁移(或重构并合并成一个新迁移)以实现所需的数据库状态。当您这样做时,您将不再向后兼容,因此不能掉以轻心,但有时这是适当的举措。

于 2013-02-08T01:17:37.880 回答