🧗
Railsで既存テーブルを削除する手順(ロールバック、復元の考慮)
最近テーブル削除のマイグレーションを書く機会があって、怖かったので自分なりの手順を整理してました。
言いたいこと
- テーブル削除に限らず、マイグレーションを書くときは原則としてロールバック可能な書き方をしよう
- ロールバックで戻せるのはあくまでスキーマであって、レコードは消えるので注意
既存のテーブルを削除したい!どんな手順で進める?
丁寧に書くと以下の手順になると思います。
- 必要に応じて、削除対象のテーブルのレコードを控えておいたり、復元スクリプトを用意しておく
-
bin/rails g migration XXX
を実行- XXXはマイグレーションクラス名(Drop<削除したいテーブル名>とか)
- 空のマイグレーションファイルが生成される
- マイグレーションファイル内に以下を記載
class XXX < ActiveRecord::Migration[7.1] def change drop_table(:<削除したいテーブル名>) do |t| end end end
-
db/schema.rb
内の、削除したいテーブルの中身(カラムやインデックスの情報)をdrop_tableのブロック内にコピペするclass XXXXX < ActiveRecord::Migration[7.1] def change drop_table(:<削除したいテーブル名>) do |t| t.string("name", null: false, comment: "名前") # カラムの情報をオプション含めてそのまま書いておくことでスキーマの復元が可能 t.integer("xxx_id", null: false) ... t.datetime("created_at", precision: nil, null: false) t.datetime("updated_at", precision: nil, null: false) t.index(["yyy_id"], name: "index_xxx_on_yyy") # indexも書いておく end end end
-
bin/rails db:migrate
を実行して成功確認- 関連部分の動作が問題ないか確認(最終確認は後でやるのでざっとでいいかも)
-
bin/rails db:rollback
を実行して成功確認-
db/schema.rb
がマイグレーション実行前の状態に戻っているか確認 - 関連部分の動作が問題ないか確認
- レコードの復元スクリプトがあるなら実行して動作確認
-
- 改めて
bin/rails db:migrate
を実行して成功確認- 最終的な動作確認をする
- コミットしてPR挙げる!
- PRにロールバックまで確認したよとか、復元スクリプト書いとくとかするとレビュアーも安心してapproveできるかも
マイグレーション実装時に考慮すべきこと
DBのバックアップさえしていれば復元はできますが、アプリケーションコードの実装段階で以下を考慮しておくべきだと思います。
- テーブルを消してから、実は消してはいけないものだったと気づいた場合にリカバリーできるか?
- コードと違ってDBはコミットdropしてforce pushとかrevertコミットとかでは戻せない
- せめてスキーマはコマンド一発で元に戻せるようにしたい(手元でロールバック確認する癖をつける)
- スキーマを復元できたとしてもレコードは消える
- テーブルの性質によっては、復元スクリプトや手順を控えておいた方がいいかも
- 例えば都道府県マスタのような、レコード数が少なめで、基本変更されないテーブルなら、コマンドだけで戻しやすいと思う
- DBのバックアップが取られていることは事前に確認すべき
マイグレーションは慎重にやっていきたいです🧗♀️
他にも留意事項とか効率いい方法とかあればぜひ教えてください!
Discussion