Ruby on Railsのschema.rbの深掘り
IT技術
なぜこの記事を書くのか
最近、Github ActionsでRailsアプリケーションの自動テストを設定する中で、schema.rb
がCI環境やテスト環境で重要な役割を果たすことを体感しました。
その際、schema.rb
が正しく管理されていないことが原因で、スキーマの不一致によるエラーや不便な点がありました。
これを機にschema.rb
の役割や管理方法をしっかりと理解しておこうと思い、ブログ執筆に至りました。
schema.rbの基本
schema.rbとは?
Railsアプリケーションのデータベース構造を記録するファイルです。
データベースのスキーマの情報がこのファイルに反映されます。
schema.rbに書かれる情報
Rails 7.1.3.4
1ActiveRecord::Schema[7.1].define(version: 2024_10_10_071952) do create_table "sample_users", id: :integer, charset: "utf8", force: :cascade do |t|
2 t.datetime "created_at", precision: nil, null: false
3 t.datetime "updated_at", precision: nil, null: false
4 t.string "name" t.string "birthday" t.text "hobby"
5 t.index ["name"], name: "index_sample_user_on_name", unique: true
6end
テーブルの定義がズラッと並びます。
内容としては、ActiveRecordのcreate_table
メソッドでテーブルを生成する記述がされています。
version: 2024_10_10_071952
はmigrationのバージョンで、DBのschema_migrations
テーブルの最新のものが反映されます。
schema_migrations
テーブルには、Rails アプリケーションでマイグレーションを実行する度にバージョンがインサートされていきます。
Railsはこのテーブルを介して、マイグレーションがどこまで実行されたかを管理しています。
rails db:schema:dumpによるschema.rbの生成・更新について
Railsでschema.rbを生成・更新するのはrails db:schema:dump
コマンドです。
rails db:migrate
で、マイグレーションを実行する際は、このrails db:schema:dump
コマンドがDBスキーマ更新後に実行され、db/schema.rb
ファイルにスキーマが出力されます。
なお、データベース上にすでにテーブルが存在し、schema_migrations
テーブルがあれば、マイグレーションファイルがなくてもrails db:schema:dump
コマンドを実行すればdb/schema.rb
に出力されます。
つまり、rails db:schema:dump
は、マイグレーションファイルを見るのではなく、実際のデータベースのスキーマを見ています。
schema.rbの役割
schema.rb
の役割はなんでしょうか?
Railsでmigrationファイルを触ったことのある人であれば、例に挙げたschema.rb
のsample_users
テーブル生成の記述は、migrationファイル
の記述ととてもよく似ていることに気がつくと思います。
schema.rb
の役割を理解するには、このmigrationファイルとの役割の違いを理解することが大切です。
両者の違いは以下になります。
migrationファイル
はスキーマの履歴を表現し、開発者が作成・管理schema.rb
は現在のスキーマの状態を表現し、Railsアプリケーションが生成・管理
migrationファイルはスキーマの履歴を表現し、開発者が作成・管理
migrationファイル
は、必要なテーブルやカラムの追加、ユニークキーやインデックスの追加を行う際に使用します。
migrationファイル
の記述後、rails db:migrate
コマンドを実行しデータベースにスキーマを反映します。
これらのmigrationファイル
をGitリポジトリ上で管理しておくことで、スキーマの変更やタイミングを開発者やRailsアプリケーションは知ることができます。
schema.rbは現在のスキーマの状態を表現し、Railsアプリケーションが生成・管理
一方で、schema.rb
はmigrationファイル
に関係なく現在のテーブルの状態を表します。
データベースのschema_migrations
テーブルの中にバージョンを表すレコードが存在すれば、rails db:schema:dump
コマンドで、現在のデータベースのスキーマをschema.rb
に出力できます。
schema.rbの使用場面
schema.rb
の使用場面として便利かつ、一般的なのはテスト用のデータベースのセットアップでしょう。
schema.rb
があればmigrationを実行せずともコマンド一つで現在運用されているデータベースのスキーマをテスト用のDBにも反映することができます。
最終的に信頼できる情報源は、やはり現在動いているデータベースです。
https://railsguides.jp/active_record_migrations.html#スキーマダンプの意義
長年開発を行っているシステムだと、migrationファイル
と実際のデータベースの状態が異なることがあります。
その状態で、migrationファイル
を元にテスト用のデータベースにrails db:migrate
を行うと、スキーマの不一致でテスト中にエラーが出ることは明白です。
CI上やローカル環境のテストでスキーマだけが欲しい場合は、最新のschema.rb
を元に、テスト用のDBにスキーマを反映するといいでしょう。
schema.rbを使用したテストDBのセットアップ手順
- migrationファイル記述
rails db:migrate
コマンドを実行しスキーマをDBとschema.rb
に反映- database.ymlにテスト用のDB接続情報を記載
rails db:setup RAILS_ENV=test
コマンドを実行しテスト用DBにスキーマを反映
大切なのでもう一度
最終的に信頼できる情報源は、やはり現在動いているデータベースです。
https://railsguides.jp/active_record_migrations.html#スキーマダンプの意義
schema.rbを使う意義・重要性
以下にschema.rb
を使う意義・重要性の代表例を挙げます
- チーム開発におけるスキーマの共有
- 他の開発者が同じスキーマを再現可能
- 自分の環境では動いたのに、あの人の環境では動かない!をなくせる。
- バージョン管理のメリット
- Gitに保存することで、スキーマの変更履歴を追跡可能
- 環境ごとの違いを防ぐ
- 特定の環境に依存しないため、移植性が高い
- CI環境でのテストDB作成。
- 複数のデータベースに接続するアプリケーションのDBセットアップ
- 特定の環境に依存しないため、移植性が高い
schema.rb管理方法
手動で編集しない!
以下、schema.rb
の編集方法です。
マイグレーションを正しく作成・実行する
前述した通り、schema.rb
は、マイグレーションの実行時や、rails db:schema:dump
コマンドで実際のDBを参照して生成されるファイルです。
手動で編集してしまうと、migrationファイルや実際のDBのスキーマとの不整合が発生し予期せぬエラーを招きます。
自動生成のトラブル
チーム開発をしている場合、schema.rb
は別の開発者が追加したスキーマでGitのコンフリクトを起こすと思います。
そういった場合は以下の手順で正しいスキーマをschema.rbに反映しましょう。
- ブランチのマージ後、
rails db:migrate
を実行し、他開発者と自分の追加したスキーマをDBに反映 schema.rb
が正しく更新されていることを確認
Git管理
- 必ず最新の状態をコミットする
- コンフリクトの解消
- 複数のブランチでマイグレーションが実行された場合、
schema.rb
はコンフリクトを起こしやすいです。丁寧に確認・解消しましょう。
- 複数のブランチでマイグレーションが実行された場合、
- コードレビューで最新であること・不備がないことを確認
正しく管理されていないとどうなる?
- 意図しないデータベース構造
- バグや障害に繋がる
- 必要なインデックスや外部キーの欠落
- コンフリクト時に正しく修正されていない場合、片方のスキーマ変更が失われる可能性がある
- 環境や開発者間でのスキーマの不整合
- デバッグの困難化
- 「環境や開発者間でのスキーマの不整合 」により環境ごとのスキーマの違いがわからず、問題が隠れてしまう。
- DBのセットアップに無駄な労力を使う
- 正しいスキーマ分からないため、不要なバグやエラーが発生し環境構築が大変になる。
- 特に新規参入者の環境構築は大変になりやすいです。
まとめ
要点
schema.rb
はRailsアプリケーションのDBを管理するためのもの- migration実行時に自動で生成・更新される
ちゃんと管理しよう!
- 適切に管理しないと、デバッグや修正作業やセットアップのコストが増大する
- 適切に管理しないと、チーム間のコンフリクトや作業が停滞が起こる
- 適切に管理していれば、DBのセットアップが簡単になる。
- 適切に管理していれば、環境の差異によるバグやエラーが出にくくなる。
参考リンク・ドキュメント
Active Record マイグレーション
https://railsguides.jp/active_record_migrations.html
所感
今まで、存在や役割も知っていましたが、今回深掘ってみてschema.rb
の強力さをより知ることができました。
また、実際に業務で触れてみることで「管理していればどう嬉しいのか」、「管理されていなければ何が困るのか」を知ることで、より知識の定着や理解が深まったと思います。
複数のDBに接続する場合でもスキーマのdumpやloadもできます。
テスト用のDBのセットアップという目的だけでなく、様々な環境にスキーマを簡単に移植できるのは嬉しいですね。
最後まで読んでいただき、ありがとうございました!
では!!
ライトコードでは、エンジニアを積極採用中!
ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。
採用情報へ
矢野健太郎です。 バスケットボールとお酒と漫画が好きです。 修行の日々です。