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

oma*_*oma 14 ruby data-migration ruby-on-rails rails-migrations

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

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

考虑一下.你有一个迁移

class ChangeFromPartnerAppliedToAppliedAt < ActiveRecord::Migration
  def up
    User.all.each do |user|
      user.applied_at = user.partner_application_at
      user.save
   end
 end
Run Code Online (Sandbox Code Playgroud)

当然,这完全没问题.稍后,您需要更改架构

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

对你来说没问题.它完美运行.但是,如果您的同事今天同时进行了这两项迁移,但尚未运行第一次迁移,那么在运行第一次迁移时会出现此错误:

rake aborted!
An error has occurred, this and all later migrations canceled:
undefined method `acceptance_confirmed_at=' for #<User:0x007f85902346d8>
Run Code Online (Sandbox Code Playgroud)

那不是团队合作者,他将修复你介绍的错误.你应该怎么做?

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

米沙的评论后编辑

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

  def up
    User.update_all('applied_at = partner_application_at')
  end
 end
Run Code Online (Sandbox Code Playgroud)

  • 被投票的人已经取消了它.别担心!显然这是正确的答案.只有一个注意@oma:我建议使用`User.update_all('applied_at = partner_application_at')`而不是`User.all.each`等. (2认同)

Chu*_*ckE 13

最佳做法是:不要在迁移中使用模型.迁移会改变AR映射的方式,因此根本不要使用它们.用SQL做到这一切.这样它总能工作.

这个:

User.all.each do |user|
  user.applied_at = user.partner_application_at
  user.save
end
Run Code Online (Sandbox Code Playgroud)

我会这样做的

update "UPDATE users SET applied_at=partner_application_at"
Run Code Online (Sandbox Code Playgroud)

  • 为什么最好不要在迁移中使用模型?有什么消息来支持吗?萨利尔的回答似乎与你的陈述相矛盾. (2认同)
  • 这是最佳实践,因为架构的固有更改会改变AR映射属性的方式.也就是说,您可能在模型实现中使用某些getter/setter /方法,最终将更新/删除.这意味着,如果您从头到尾运行迁移,它们将会中断.你将永远依赖于拥有稳定的架构.当然,我的主要论点是:迁移在数据库上工作,所以他们应该用那里理解的语言说话.甚至rails用于迁移的DSL(create_table,以及所有这些)最终被转换为原始SQL.允许实例化AR模型 (2认同)
  • 好的,那是你的看法.没问题.但是,如果这是一种最佳实践,正如您声称的那样,必须有一些来源支持它.优选地由Rails核心成员. (2认同)