14

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

我试着举一个例子来澄清这个问题:

考虑一下。你有一个迁移

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>

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

4

3 回答 3

14

这是一个完美的例子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

在米莎的评论后编辑

class ChangeFromPartnerAppliedToAppliedAt < ActiveRecord::Migration
  class User < ActiveRecord::Base
  end

  def up
    User.update_all('applied_at = partner_application_at')
  end
 end
于 2012-10-24T08:33:21.110 回答
13

最佳实践是:不要在迁移中使用模型。迁移会改变 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"
于 2012-10-24T08:33:27.633 回答
0

有时“迁移数据”不能作为模式迁移的一部分执行,就像上面讨论的那样。有时“迁移数据”意味着“修复历史数据不稳定”或“更新 Solr/Elasticsearch”索引,因此这是一项复杂的任务。对于这类任务,请查看此 gem https://github.com/OffgridElectric/rails-data-migrations

该 gem 旨在将 Rails 模式迁移与数据迁移分离,因此在部署时不会导致停机,并且整体上易于管理

于 2016-11-07T12:20:53.253 回答