迁移数据 - 不仅仅是模式,Rails

时间:2012-10-24 08:27:55

标签: ruby-on-rails ruby data-migration rails-migrations

有时,数据迁移是必需的。随着时间的推移,使用域模型的代码更改和迁移不再有效,迁移失败。迁移数据的最佳做法是什么?

我尝试了一个例子来澄清问题:

考虑一下。你有一个迁移

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>

那不是团队合作者,他将修复你引入的错误。你应该怎么做?

3 个答案:

答案 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模式迁移与数据迁移分离,因此它不会在部署时导致停机并使其易于整体管理