나는 이벤트 테이블과 세션 테이블을 가지고 있습니다. 이벤트 has_many 세션, 이것은 협회입니다. 이제 세션 테이블의 time_zone 열을 이벤트 테이블로 이동하려고합니다. 그렇다면 마이그레이션의 도움으로 어떻게해야합니까? 세션 테이블의 time_zone에 대한 기존 레코드를 이벤트 테이블로 이동하려면 어떻게합니까?레일 마이그레이션의 데이터로 열 업데이트
답변
다음 마이그레이션을 사용하면됩니다.
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
먼저 동일한 이벤트와 연결된 세션이 동일한 표준 시간대를 유지해야합니다. 그와 관련된 시간대의 수에 event_id
매핑 해시를 반환합니다
Session.group(:event_id).count(:time_zone)
이 : 당신은이 작업을 수행 할 수 있습니다. 이 번호는 항상 하나 여야합니다.
둘째로, 새로운 코드가 생산 중이며 얼마 동안 작동 한 후에 별도의 마이그레이션에서 을 추가하고 사용을 시작하여 sessions.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
참고 :
셋째, 다음과 같이한다 events.time_zone
를 추가 할 수있는 마이그레이션 (I 명확성에 대한 몇 가지 의견을 추가). 그 이유는 다음과 같습니다.
- 원본 모델에 콜백 및 유효성 검사가 적용될 수 있습니다 (물론 건너 뛸 수 있지만 값이 0 인 추가주의 사항).
- 도로를 6 개월 만에 모델을 제거하면 마이그레이션이 중단됩니다.
변경 사항이 예상대로 작동하면 sessions.time_zone
을 제거 할 수 있습니다. 오류가 발생하면 위의 마이그레이션을 롤백하고 작업 버전을 쉽게 복원 할 수 있습니다.
이것은 작동합니다. 다운 된 경우 세션 테이블에서 time_zone을 복원 할 수있는 방법이 없어야합니까? – Nikhil
** sessions.time_zone을 제거하지 ** 않았습니다 **. 마지막 단락을 참조하십시오. - 먼저 새 열로 마이그레이션하고 코드에서 사용하도록 설정하고 작동하면 이전 열을 제거하는 것이 좋습니다. 데이터베이스 저장소가 저렴하기 때문에 서두를 필요가 없습니다. –
아 .. 그 부분을 놓쳤습니다.이 다음에 도움이됩니다. events_sessions 테이블과 같은 연결을 저장하기 위해 세 번째 테이블을 만드는 것이 합리적일까요? – Nikhil
마이그레이션 할 때 모델을 사용하면 안됩니다. 콜백, 유효성 검사 등을 트리거 할 수 있으며 시간에 따라 변경할 수 있습니다 (예 : 6 개월 후에 모델을 삭제하면 이전이 중단됨). –