Railsのdb/schema.rbの役割


db/schema.rbは何に使われるのか

rake db:migrateなどをすると現在のスキーマが反映され、スキーマの確認などに便利なschema.rb。
ふと、1つのRailsアプリを分割して、複数のRailsアプリから同じDBを参照するようにしたくなったのだが、その際にどちらのRailsアプリにもdb/schema.rbを含める必要があるのか気になった。

db/schema.rbを削除してもアプリは動くのだが、
schema.rbには「It's strongly recommended that you check this file into your version control system.」と書いてあるので、本当に削除していいのか自信がない。

そこで、Rails4.1.5のソースを読んで、schema.rbがどんな用途に使われているのかを調査した。

schema.rbが使われている3箇所

rails/railsのファイル全てに対してschema.rbでgrepをかけると、3箇所で使われていることがわかる。

  • ActiveRecord::Railtieのinitializer
  • ActiveRecord::Tasks::DatabaseTasks
  • active_record/railties/databases.rake

それぞれが最終的にどのような役割を果たすか説明する。

1. ActiveRecord::Railtieのinitializer

ActiveRecord::Railtie内に定義されているinitializerで、config.watchable_filesdb/schema.rbを追加している
読み進めていくと、watchable_filesはこのへんで使われていて、watchable_filesが更新されたときに、読み込んだ依存関係をクリアするようになっている。

つまり、schema.rbがあると、そのアプリでスキーマを更新した後、依存関係の再読み込みが行われるようになる
別のアプリ等でスキーマ管理をする場合は、スキーマが更新されたらこの仕組みを使う(rake db:schema:load等)か何らかの方法で読み込んだ依存関係をクリアする必要がある。

2. ActiveRecord::Tasks::DatabaseTasks

これは実際のところ3でのみ使われるモジュールである。
3がdb/schema.rbを読み込むときに使われる。

3. active_record/railties/databases.rake

rake db:** のタスクが定義されているファイル。
この中で、schema.rbを使うタスクは以下のとおりであった。 (deprecatedなものを除く)

  • rake db:schema:dump
    • db:migratedb:rollback などが依存している
    • 現在のスキーマからschema.rbを作成する
  • rake db:schema:load
    • db:setupdb:reset などが依存している
    • schema.rbからテーブルを作成する

要するにschema.rbにスキーマ定義をダンプしたり、schema.rbからダンプしておいたスキーマを再現するのに使える。

試しでインデックスを張り替えたりしていると本来のスキーマとずれてしまうことがあると思うが、その際にschema.rbがあれば元の状態に復元できるので、複数の環境間でスキーマの整合性を保つためにschema.rbは1つはあったほうが良い
逆に、1つschema.rbがどこかで管理されていれば、同じDBを使う他のrailsアプリではschema.rbは配置しなくて良いと言える。

まとめ

db/schema.rbはなくても動くが、複数の環境間でスキーマの整合性を保つためにどこかに1つは管理しておくべきである。