Как перенести существующие данные после добавления полиморфной ассоциации?

После миграции моя таблица PageViewStats содержит 2 новых пустых столбца: ad_templatable_id и ad_templatable_type. Поэтому, если я попытаюсь запросить существующую запись следующим образом: AdTemplate.find(42).page_view_stats, она ничего не вернет, но перед миграцией она вернет массив из PageViewStats записей.

Думаю, мне нужно создать задачу rake, которая заполнит эти 2 новых столбца:

1) ad_templatable_id будет содержать значения из существующего столбца ad_template_id

2) ad_templatable_type будет содержать строку AdTemplate

Моя догадка верна? :) Это то, что мне нужно сделать?

Перед миграцией:

# == Schema Information
# #  ad_template_id      :integer          not null
class PageViewStat < ActiveRecord::Base
  belongs_to :ad_template
end

class AdTemplate < ActiveRecord::Base
  has_many :page_view_stats
end

Применение полиморфной миграции:

class AddPolymorphismToPageViewStat < ActiveRecord::Migration
  def change
    add_reference :page_view_stats, :ad_templatable, polymorphic: true
    add_index :page_view_stats, [:ad_templatable_type, :ad_templatable_id],
               name: 'index_page_view_stats_on_ad_templatable_type_and_id'
  end
end

После переноса:

# == Schema Information
# #  ad_template_id      :integer          not null
class PageViewStat < ActiveRecord::Base
  belongs_to :ad_templatable, polymorphic: true
end

class AdTemplate < ActiveRecord::Base
  has_many :page_view_stats, as: :ad_templatable
end

person yaru    schedule 28.02.2017    source источник


Ответы (1)


Да, создание rake-задачи лучше, чем выполнение миграции данных вручную, так как для нее можно написать тесты.

Другой способ — включить код для изменения данных при миграции, что отлично подходит для обеспечения переноса данных при изменении схемы, что сокращает потенциальное время простоя, например.

def up
  [code to add new columns]

  migrate_data

  [code to remove legacy columns]
end

def down
  [code to add legacy columns]

  rollback_data

  [code to remove new columns]
end

private

def migrate_data
  [code to make data changes]
end

def rollback_data
  [code to reverse data changes]
end

Обратите внимание, что если вы сделаете это таким образом, есть некоторые ошибки, вам нужно будет указать миграцию вверх и вниз отдельно, и вам придется приложить усилия для написания кода для отката, а также для тестирования.

person Nicholas.V    schedule 28.02.2017