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

Ada*_*sek 3 migration ruby-on-rails ruby-on-rails-3

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

class Location < ActiveRecord::Base
  attr_accessible :company_name, :location_name
end
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

Jon*_*nah 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
Run Code Online (Sandbox Code Playgroud)