• トップ
  • ブログ一覧
  • Ruby on Railsのschema.rbの深掘り
  • Ruby on Railsのschema.rbの深掘り

    なぜこの記事を書くのか

    最近、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.rbsample_usersテーブル生成の記述は、migrationファイルの記述ととてもよく似ていることに気がつくと思います。

    schema.rbの役割を理解するには、このmigrationファイルとの役割の違いを理解することが大切です。

    両者の違いは以下になります。

    • migrationファイルはスキーマの履歴を表現し、開発者が作成・管理
    • schema.rbは現在のスキーマの状態を表現し、Railsアプリケーションが生成・管理

    migrationファイルはスキーマの履歴を表現し、開発者が作成・管理

    migrationファイルは、必要なテーブルやカラムの追加、ユニークキーやインデックスの追加を行う際に使用します。
    migrationファイルの記述後、rails db:migrateコマンドを実行しデータベースにスキーマを反映します。
    これらのmigrationファイルをGitリポジトリ上で管理しておくことで、スキーマの変更やタイミングを開発者やRailsアプリケーションは知ることができます。

    schema.rbは現在のスキーマの状態を表現し、Railsアプリケーションが生成・管理

    一方で、schema.rbmigrationファイルに関係なく現在のテーブルの状態を表します。
    データベースの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のセットアップ手順

    1. migrationファイル記述
    2. rails db:migrateコマンドを実行しスキーマをDBとschema.rbに反映
    3. database.ymlにテスト用のDB接続情報を記載
    4. 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に反映しましょう。

    1. ブランチのマージ後、rails db:migrateを実行し、他開発者と自分の追加したスキーマをDBに反映
    2. 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のセットアップという目的だけでなく、様々な環境にスキーマを簡単に移植できるのは嬉しいですね。

    最後まで読んでいただき、ありがとうございました!
    では!!

    ライトコードでは、エンジニアを積極採用中!

    ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。

    採用情報へ

    やのけん(エンジニア)
    やのけん(エンジニア)
    Show more...

    おすすめ記事

    エンジニア大募集中!

    ライトコードでは、エンジニアを積極採用中です。

    特に、WEBエンジニアとモバイルエンジニアは是非ご応募お待ちしております!

    また、フリーランスエンジニア様も大募集中です。

    background