2017-01-10 3 views
0

У меня есть таблица событий и таблица сеансов. События has_many сеансы, это ассоциация. Теперь я хочу переместить столбец time_zone из таблицы сеансов только в таблицу событий. Итак, как мне это сделать с помощью миграции. Как перенести существующие записи для time_zone в таблицу сеансов в таблицу событий?Обновить столбец с данными в миграции рельсов

ответ

-1

Вы можете просто использовать следующую миграцию.

class Test < ActiveRecord::Migration 
    def change 
    add_column :events, :time_zone, :string 

    Event.all.each do |e| 
     e.update_attributes(time_zone: e.sessions.last.time_zone) 
    end 

    remove_column :sessions, :time_zone 
    end 
end 
+0

Вы не должны использовать модели при миграции. Они могут активировать обратные вызовы, проверки и т. Д., И они могут со временем меняться (т. Е. Если вы удалите модель через 6 месяцев, миграция перестанет работать). –

1

Во-первых, вы должны быть уверены, что сеансы, связанные с одним и тем же событием, имеют один и тот же часовой пояс. Вы можете сделать это с помощью:

Session.group(:event_id).count(:time_zone) 

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

Во-вторых, я рекомендую вам сначала добавить events.time_zone и начать использовать его и удалить sessions.time_zone в отдельную миграцию после того, как новый код был в производстве в течение некоторого времени и доказал свою эффективность.

В-третьих, миграция добавить events.time_zone должен выглядеть следующим образом (я добавил некоторые комментарии для ясности):

class AddTimeZoneToEvents < ActiveRecord::Migration 
    class Event < ActiveRecord::Base; end 
    class Session < ActiveRecord::Base; end 

    def up 
    # Add a NULLable time_zone column to events. Even if the column should be 
    # non-NULLable, we first allow NULLs and will set the appropriate values 
    # in the next step. 
    add_column :events, :time_zone, :string 

    # Ensure the new column is visible. 
    Event.reset_column_information 

    # Iterate over events in batches. Use #update_columns to set the newly 
    # added time_zone without modifying updated_at. If you want to update 
    # updated_at you have at least two options: 
    # 
    # 1. Set it to the time at which the migration is run. In this case, just 
    #  replace #update_columns with #update! 
    # 2. Set it to the maximum of `events.updated_at` and 
    #  `sessions.updated_at`. 
    # 
    # Also, if your database is huge you may consider a different query to 
    # perform the update (it also depends on your database). 
    Event.find_each do |event| 
     session = Session.where(event_id: event.id).last 
     event.update_columns(time_zone: session.time_zone) 
    end 

    # If events don't always need to have time zone information then 
    # you can remove the line below. 
    change_column_null :events, :time_zone, false 
    end 

    def down 
    remove_column :events, :time_zone 
    end 
end 

Обратите внимание, что я переопределен модели в процессе миграции. Крайне важно это сделать, потому что:

  1. Оригинальная модель может иметь обратные вызовы и проверки (конечно, вы можете пропустить их, но это одна дополнительная мера предосторожности, которая вносит нулевое значение).
  2. Если вы удалите модели через 6 месяцев после этого, миграция перестанет работать.

Как только вы убедитесь, что ваши изменения работают нормально, вы можете удалить sessions.time_zone. Если что-то пойдет не так, вы можете просто отбросить вышеуказанную миграцию и легко восстановить рабочую версию.

+0

Это работает. Что в случае отказа, не должен ли быть какой-либо метод, который восстановит time_zone в таблице сеансов? – Nikhil

+0

Обратите внимание, что я не ** ** удалял 'session.time_zone'. См. Последний параграф. Я рекомендую вам сначала перенестись в новый столбец, сделать свой код его, и как только вы убедитесь, что он работает, удалите старый столбец. Хранилище базы данных дешево, поэтому нет спешки. –

+0

Ох .. Я пропустил эту часть .. это помогает тогда .. будет ли смысл создавать третью таблицу для хранения ассоциаций что-то вроде таблицы events_sessions? – Nikhil

Смежные вопросы