有时,数据迁移是必需的。随着时间的推移,使用域模型的代码更改和迁移不再有效,迁移失败。迁移数据的最佳做法是什么?
我尝试了一个例子来澄清问题:
考虑一下。你有一个迁移
class ChangeFromPartnerAppliedToAppliedAt < ActiveRecord::Migration
def up
User.all.each do |user|
user.applied_at = user.partner_application_at
user.save
end
end
当然,这完全没问题。稍后,您需要更改架构
class AddAcceptanceConfirmedAt < ActiveRecord::Migration
def change
add_column :users, :acceptance_confirmed_at, :datetime
end
end
class User < ActiveRecord::Base
before_save :do_something_with_acceptance_confirmed_at
end
对你来说,没问题。它完美运行。但是,如果您的同事今天同时提取这两个,尚未运行第一次迁移,他将在运行第一次迁移时遇到此错误:
rake aborted!
An error has occurred, this and all later migrations canceled:
undefined method `acceptance_confirmed_at=' for #<User:0x007f85902346d8>
那不是团队合作者,他将修复你引入的错误。你应该怎么做?
答案 0 :(得分:15)
这是Using Models in Your Migrations
class ChangeFromPartnerAppliedToAppliedAt < ActiveRecord::Migration
class User < ActiveRecord::Base
end
def up
User.all.each do |user|
user.applied_at = user.partner_application_at
user.save
end
end
在Mischa的评论之后编辑
class ChangeFromPartnerAppliedToAppliedAt < ActiveRecord::Migration
class User < ActiveRecord::Base
end
def up
User.update_all('applied_at = partner_application_at')
end
end
答案 1 :(得分:14)
最佳做法是:不要在迁移中使用模型。迁移会改变AR映射的方式,因此根本不要使用它们。用SQL做到这一切。这样它总能工作。
此:
User.all.each do |user|
user.applied_at = user.partner_application_at
user.save
end
我会喜欢这个
update "UPDATE users SET applied_at=partner_application_at"
答案 2 :(得分:0)
有些时候,“迁移数据”无法作为架构迁移的一部分执行,如上所述。有时,“迁移数据”意味着“修复历史数据不一致”或“更新您的Solr / Elasticsearch”索引,因此这是一项复杂的任务。对于这些任务,请查看此gem https://github.com/OffgridElectric/rails-data-migrations
此gem旨在将Rails模式迁移与数据迁移分离,因此它不会在部署时导致停机并使其易于整体管理