你如何应对Rails迁移中的变化?

时间:2011-01-13 00:42:06

标签: ruby-on-rails migration ruby-on-rails-3

假设我开始使用这个模型:

class Location < ActiveRecord::Base
  attr_accessible :company_name, :location_name
end

现在我想将其中一个值重构为关联模型。

class CreateCompanies < ActiveRecord::Migration
  def self.up
    create_table :companies do |t|
      t.string :name, :null => false
      t.timestamps
    end

    add_column :locations, :company_id, :integer, :null => false
  end

  def self.down
    drop_table :companies
    remove_column :locations, :company_id
  end
end

class Location < ActiveRecord::Base
  attr_accessible :location_name
  belongs_to :company
end

class Company < ActiveRecord::Base
  has_many :locations
end

这一切在开发过程中都很好,因为我一步一步都做到了;但如果我尝试将其部署到我的临时环境中,我就会遇到麻烦。

问题在于,由于我的代码已经更改以反映迁移,因此在尝试运行迁移时会导致环境崩溃。

还有其他人处理过这个问题吗?我是否已经辞职将我的部署分成多个步骤?

更新看来我错了;在迁移同事的环境时,我们遇到了麻烦,但暂存更新没有问题。 Mea Culpa。我会将@ noodl的回复标记为埋葬这个的答案,无论如何,他的帖子都是好建议。

2 个答案:

答案 0 :(得分:9)

我认为这里的解决方案是不编写具有任何外部依赖关系的迁移。您的迁移不应依赖于模型的过去或当前状态才能执行。

这并不意味着您无法使用模型对象,只是在运行特定迁移时不应使用在任何版本的代码中找到的版本。

而是考虑在迁移文件中重新定义模型对象。在大多数情况下,我发现扩展ActiveRecord::Base的空模型类或我编写迁移时使用的模型类的非常精简的版本允许我编写可靠的,未来证明,迁移而无需将ruby逻辑转换为SQL。

#20110111193815_stop_writing_fragile_migrations.rb
class StopWritingFragileMigrations < ActiveRecord::Migration
  class ModelInNeedOfMigrating < ActiveRecord::Base
    def matches_business_rule?
      #logic copied from model when I created the migration
    end
  end
  def self.up
    add_column :model_in_need_of_migrating, :fancy_flag, :boolean, :default => false

    #do some transform which would be difficult for me to do in SQL
    ModelInNeedOfMigrating.all.each do |model|
      model.update_attributes! :fancy_flag => true if model.created_at.cwday == 1 && model.matches_business_rule?
      #...
    end
  end

  def self.down
    #undo that transformation as necessary
    #...
  end
end

答案 1 :(得分:0)

运行迁移时会出现什么错误?只要您的rake文件和迁移不使用您的模型(并且它们不应该),您应该没问题。

您还需要在迁移的self.down中切换drop_table和remove_column行的顺序。