Подтвердить что ты не робот

Миграция DATA - не только схемы, Rails

Иногда требуется миграция данных. По прошествии времени изменения кода и миграции с использованием вашей модели домена перестают быть действительными, а миграции не выполняются. Каковы наилучшие методы переноса данных?

Я попытался сделать пример, чтобы прояснить проблему:

Рассмотрим это. У вас есть миграция

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>

Чтобы не быть игроком в команде, он будет исправлять введенную вами ошибку. Что вы должны были сделать?

4b9b3361

Ответ 1

Лучшая практика: не используйте модели в миграциях. Миграции меняют способ отображения карт 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

Это прекрасный пример 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

Ответ 3

Некоторое время "миграция данных" не может выполняться как часть миграции схемы, как обсуждалось выше. Иногда "перенос данных" означает "фиксировать непостоянство исторических данных" или "обновлять индекс Solr/Elasticsearch", поэтому его сложная задача. Для этих задач проверьте этот драгоценный камень https://github.com/OffgridElectric/rails-data-migrations

Этот жемчуг был разработан для того, чтобы развязать миграции схем Rails с миграциями данных, поэтому он не вызывает время простоя во время развертывания и упрощает управление в целом