假设我从这个模型开始:
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
这在开发过程中一切正常,因为我一步一步地做所有事情;但是如果我尝试将它部署到我的暂存环境中,我会遇到麻烦。
问题在于,由于我的代码已经更改以反射(reflect)迁移,因此在尝试运行迁移时会导致环境崩溃。
还有其他人处理过这个问题吗?我是否愿意将我的部署分成多个步骤?
更新看来我弄错了;在迁移同事的环境时,我们遇到了麻烦,但升级时没有问题。过错。我会将@noodl 的回复标记为埋葬这个问题的答案,无论如何他的帖子都是很好的建议。
最佳答案
我认为这里的解决方案是不要编写具有任何外部依赖项的迁移。您的迁移不应依赖于模型的过去或当前状态才能执行。
这并不意味着您不能使用模型对象,只是您不应该使用在运行特定迁移时碰巧安装的代码版本中找到的版本。
请考虑在迁移文件中重新定义模型对象。在大多数情况下,我发现扩展 ActiveRecord::Base
的空模型类或我在编写迁移时使用的模型类的非常精简的版本允许我可以编写一个可靠的、面向 future 的迁移,而无需将 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
关于ruby-on-rails - 您如何处理 Rails 迁移中的重大更改?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4675672/