Railsのマイグレーションに対するいらだち
ローカルでのスキーマの試行錯誤に弱い
このフラストレーションが一番大きい。
特に新しい機能を開発しているような場合、コードを書きながらスキーマを微調整していくことがある。マイグレーションファイルを編集しながら db:migrate:redo
を繰り返していくことになるのだが、これが全然ロバストでなく、行き詰まりやすすぎる。
たとえば、こんなマイグレーションを書いて、 db:migrate
する。
add_column :recipes, :calories
直後、ああ calories
ではなく energy
のほうが良かったな、と思う。理由はなんでもいい。とにかくカラム名を変えたい。マイグレーションを編集して db:migrate:redo
しよう。
-add_column :recipes, :calories
+add_column :recipes, :energy
さてどうなるだろうか。 db:migrate:redo
は down → up と等価なので、まずは energy
カラムの削除が試みられ、当然 Unknown column 'column_bar'
エラーが起こる。南無。
いったん calories
に戻してdownしたのち、再び energy
に変更してupする手順を踏む必要がある。もしくは手動でALTER TABLEして直すか。その場合は db:schema:dump
して schema.rb を更新するのをお忘れなく。
もっと悪いことになる例。こんなマイグレーションを書く。2行目の remove_column
だけが失敗したとする。
add_column :table, :column_foo
remove_column :table, :colmun_bar # typo があり、存在しないカラムになる
このとき、マイグレーション全体としては成功していないので、未実行状態になる。 remove_column
を修正して再実行したときは add_column
から走り直すが、 column_foo
の作成自体は成功しているので、今度は Duplicate column name 'column_foo'
エラーで失敗になる。南無。
こうなるとupもdownもできない。手動でALTER TABLEで column_foo
を消して整合性を取るか、あるいは一時的に add_column
の行を消してmigrationを成功させ、その後行を戻す対処しか思いついていない。
これを確実に回避するためには、1 migrationごとに流すDDLは一つだけにするしかない。常に change_table(bulk: true)
だけを使えばいい話ではある、のだが……。1つのmigrationファイルで実行されるDDLの数、常に意識していますか?
複数ブランチで開発を同時進行していると、schema.rbの生成結果が混ざる
ブランチAで以下のマイグレーションを流して
add_column :users, :column_a, :integer
ブランチBに切り替え、以下のマイグレーションを流すと
add_column :users, :column_b, :integer
schema.rbはこうなる。schema.rbは常に db:schema:dump
から生成されるので、現在のブランチにはないマイグレーションの結果であれ、データベースに存在するカラムはすべて記述されてしまう。
create_table "users" do |t|
t.integer "id"
+ t.integer :column_a # このブランチには存在しない migration の結果!
+ t.integer :column_b
end
schema.rb は常に git add -p
でチェックしているけれど、これが幸せかというと、どうだろう。
(ぼやいていたら、この問題に自動で対処できる widefix/actual_db_schema というツールを教えてもらいました。便利!)
git revertによるロールバックが困難
こちらは本番環境での話。
マイグレーションした結果、何かマズいことが起こり git revert
をしたとき、migrationファイルは消え去る。消え去ったmigrationファイルに記述されていたALTER TABLEは取り消されるわけでもなく、ただファイルが消える。こうなると db:rollback
(down) もできない。
障害が起きているようなシーンでは、行動の択を絞ることが重要。正確なタイミングで db:rollback
することを意識することはけっこう難しい。
なお、本番環境でなくてもgit revertされたケースが積み重なってくると、schema.rbの正しさも信用できなくなってくる。"正しい" スキーマが何か分からなくなるのは困る。
比較的ささいな話
- 単純に覚えることが多い
- がんばって記憶してます
- あとはドキュメントのURLを覚えました
- schema.rb が高頻度でコンフリクトする
- Migrationを追加するたび、schema.rbの先頭にある
version
部分が書き換わる。複数人で開発していると極めて容易にコンフリクトする。ActiveRecord::Schema[8.0].define(version: 2025_07_24_123456) do
- rebaseすればいい話ではあるが
- こういう細かいいらだちが積み重なっている
- Migrationを追加するたび、schema.rbの先頭にある