概要
本番運用中プロダクトへの機能追加対応により
1つのテーブルを2つにわける必要がありました。
当然ながら既存データの移行も考慮しないといけない。
作業手順としては
Railsマイグレーション機能で2つの新しいテーブル作成,
SQLによるデータ移行が
考えられましたが、
今回はデータ移行もRailsマイグレーション機能で同時に行ってみました。
開発環境
- Ruby 2.6.5
- Rails 5.2.4
- PostgreSQL 9.6
既存テーブル構成と分割後の構成
作業詳細
-
新しいテーブル作成 -> データ移行
順でマイグレーションが実行されるよう、マイグレーションファイルを作成する
1. 新しいテーブル作成マイグレーションファイル
- 数学スコア用のRailsマイグレーション作成
class CreateResultMathScores < ActiveRecord::Migration[5.2]
def change
t.references :user, foreign_key: true, null: false
t.float :score, null: false, comment: "数学スコア"
t.timestamps
end
end
- 英語スコア用のRailsマイグレーション作成
class CreateResultEnglishScores < ActiveRecord::Migration[5.2]
def change
t.references :user, foreign_key: true, null: false
t.float :score, null: false, comment: "英語スコア"
t.timestamps
end
end
2. データ移行マイグレーションファイル
- データ移行用のマイグレーションは
rails db:rollback
を考慮しdef up
def down
で作成する - ActiveRecord Modelを使ったデータ移行も可能だが、このマイグレーションの責務はデータ移行なので
Modelに依存しない形にしました
class DataMigrationResultScoresToResultMathScoresAndResultEnglishScores < ActiveRecord::Migration[5.2]
def up
ActiveRecord::Base.transaction do
execute <<-SQL
insert into result_math_scores
(
user_id,
score
create_at
update_at
)
select
user_id,
math_score,
now(),
now()
from
result_scores
SQL
execute <<-SQL
insert into result_english_scores
(
user_id,
score
create_at
update_at
)
select
user_id,
english_score,
now(),
now()
from
result_scores
SQL
end
end
def down
ActiveRecord::Base.transaction do
execute <<-SQL
delete from result_math_scores
SQL
execute <<-SQL
delete from result_english_scores
SQL
end
end
end
3. 既存テーブルの削除
既存テーブル(result_scores)のDropは
今のところ削除せず、様子見の予定。
結論
Railsマイグレーションでテーブル作成とデータ移行を一緒にやらない方がいいという
意見もあるようですが、rails db:rollback
を考慮したマイグレーションであれば
問題ないかと思います。