🐥

【初心者向け】ブランチを切り替えてもなぜマイグレーションがスキーマに反映されてしまうのか

2022/10/20に公開

はじめに

Ruby on Railsをgit管理をしながら開発しています。

ブランチAでマイグレーションrails db:migrateを実行した後に、ブランチBに切り替えてrails db:migrateをするとマイグレーションファイルにはないはずのschema.rbにはブランチAのマイグレーション差分が発生してしまいます。

そのため、ブランチAで実行したマイグレーションはrails db:rollbackしてからブランチBに変更するか、大規模なロールバックの場合はrails db:resetをするかどちらかの対応になるかと思います。

ただ、よくよく考えてみるとマイグレーションファイルからスキーマファイルを生成している、だけの知識では何故こうなるのかの説明がつかないです。

今回はマイグレーションファイルは存在しないはずなのになぜそのようなことになるのか、推測含めまとめました。

マイグレーションファイルでスキーマファイルは管理されているのか?

Railsマイグレーションのドキュメントを読んでみます。

スキーマファイルの意味について
Railsのマイグレーションは強力ではありますが、データベースのスキーマを作成するための信頼できる情報源ではありません。信頼できる情報源は、やはりデータベースです。Railsは、デフォルトでdb/schema.rbファイルを生成してデータベーススキーマの最新の状態のキャプチャを試みます。

db/schema.rbやdb/structure.sqlは、使っているデータベースの最新ステートのスナップショットであり、そのデータベースを再構築するための情報源として信頼できます。

マイグレーションファイルからのみでスキーマファイルを作成しているかと思いきや、ここを見るとどうやらそれだけではなさそうです。

実際にはデータベースのデータから差分を見ていることがわかります。

ではデータベースのどこで管理しているか?

db/migrate/ディレクトリ内のマイグレーションファイルを削除しても、マイグレーションファイルが存在していたときにrails db:migrateが実行されたあらゆる環境は、Rails内部のschema_migrationsという名前のデータベース内に保存されている(マイグレーションファイル固有の)マイグレーションタイムスタンプへの参照を保持し続けます。このテーブルは、特定の環境でマイグレーションが実行されたことがあるかどうかをトラッキングするのに用いられます。

データベース内のテーブルを見てみましょう。おそらくschema_migrationsというテーブルが存在していると思います。

schema_migrationsで一度実行されたマイグレーションファイルのタイムスタンプを保存しています。

rails db:migrateされたタイミングでこのテーブルを確認しており、存在しないマイグレーションファイルに関してはデータベースからスキーマファイルを生成、みたいなことがされてると推測されます(githubみましたが推測の域を出ませんでした。詳しい方いたらコメント是非お願いします!)。

参考

https://railsguides.jp/active_record_migrations.html
https://github.com/rails/rails

GitHubで編集を提案

Discussion