※本記事は「RailsからLaravelを眺める」シリーズの第7回です。Rails出身の私がLaravelを触りながら、Railsと比較して違いを整理していく連載になります。
はじめに
RailsでもLaravelでも、アプリ開発を始めると必ず登場するのが DBマイグレーション。
テーブルやカラムをコードで管理できるのは便利ですが、数年単位で運用すると マイグレーションファイルが雪だるま式に膨れる という課題に直面します。
この問題に対応するため、Rails界隈では Ridgepole、Laravel界隈では sqldef を採用するプロジェクトが増えています。
今回は標準migrateを整理した上で、Ridgepoleとsqldefとは何者なのか、どう違うのかをサンプルコード多めで紹介します。
Rails標準のmigrate
基本の流れ
bin/rails generate migration AddAgeToUsers age:integer
bin/rails db:migrate
生成されるファイル例:
class AddAgeToUsers < ActiveRecord::Migration[8.0]
def change
add_column :users, :age, :integer
end
end
db/schema.rb
create_table "users", force: :cascade do |t|
t.string "name"
t.integer "age"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
メリット
- Rails Wayに統合されている
- ActiveRecordとの連動が自然
デメリット
- マイグレーションファイルが積み上がる
- 大規模プロジェクトでは管理が困難
Laravel標準のmigrate
基本の流れ
php artisan make:migration add_age_to_users_table --table=users
php artisan migrate
生成されるファイル例:
return new class extends Migration {
public function up(): void {
Schema::table('users', function (Blueprint $table) {
$table->integer('age')->nullable();
});
}
public function down(): void {
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('age');
});
}
};
メリット
- SeederやFactoryと統合しやすい
- API開発との親和性が高い
デメリット
- Railsと同じく積み上げ式
- 長期運用でフォルダが膨張
Ridgepoleとは?
Ridgepoleは、Rails界隈で広く使われている DBスキーマ管理ツール です。
特徴
- スキーマを
Schemafile
に宣言的に記述 - DBとの差分を検出し、自動で
ALTER TABLE
を生成・適用 - ActiveRecord DSLに近い書き方ができる
サンプル
Schemafile
create_table "users", force: :cascade do |t|
t.string "name", null: false
t.integer "age"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
適用
bundle exec ridgepole --apply -f Schemafile --config config/database.yml
メリット
- Railsの世界観にマッチしている
- スキーマの状態を一元管理できる
- 過去のマイグレーション履歴を気にせずDBを再現可能
sqldefとは?
sqldefは、Laravelやその他言語でも利用される SQLベースのスキーマ管理ツール です。
特徴
- SQLファイルでスキーマを定義
--apply
コマンドで差分を自動検出・適用- MySQL/PostgreSQL/SQLiteなど幅広く対応
- 言語に依存せず、Rails/Laravel問わず利用可能
サンプル
初期エクスポート:
mysqldef -u root -p myapp_db --export > schema.sql
schema.sql
CREATE TABLE users (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
age INT,
created_at DATETIME NOT NULL,
updated_at DATETIME NOT NULL
);
適用:
mysqldef -u root -p myapp_db --apply < schema.sql
差分例:
ALTER TABLE users ADD COLUMN age INT;
メリット
- SQLなので直感的で学習コストが低い
- 言語非依存、チーム混在環境でも使いやすい
- CI/CDとの相性が良い
Ridgepoleとsqldefの違い
項目 | Ridgepole | sqldef |
---|---|---|
言語 | Ruby | Go |
定義ファイル | Ruby DSL (Schemafile ) | SQL (schema.sql ) |
適用方法 | ridgepole --apply | sqldef --apply |
対応DB | MySQL / PostgreSQL | MySQL / PostgreSQL / SQLite 他 |
フレームワーク親和性 | Rails文化圏 | 言語非依存(Laravelで採用増) |
学習コスト | Rails経験者に低い | SQLが分かれば誰でも扱える |
実務での選び方
Railsアプリを運用するなら
- 小〜中規模・短期開発:標準の
db/migrate
で十分。 - 中〜大規模・長期運用:Ridgepoleを導入することで、Schemafile一発でDBを再現できる。
- CI/CD:Schemafileをコミットしておけば、テスト環境や本番リリースでの事故を大幅に減らせる。
Laravelアプリを運用するなら
- 小規模・初期フェーズ:
php artisan migrate
で十分。Seederとの組み合わせも便利。 - 成長期・チーム開発本格化:sqldefで状態同期を導入すれば、マイグレーション地獄を回避できる。
- マルチ言語環境:バックエンドがLaravelでも、フロントや別サービスがGo/Nodeの場合はSQLベースのsqldefが強い。
両者に共通する実務的判断基準
- DBをどう位置づけるか
- アプリの一部 → 標準migrate
- インフラ資産 → Ridgepole / sqldef
- プロジェクト寿命
- 短期(PoC、数ヶ月) → 標準migrate
- 長期(数年〜) → 状態同期型を検討
- 開発体制
- 少人数 → 標準migrate
- 複数チーム・複数言語 → sqldef/Ridgepole
まとめ
RailsとLaravelの標準migrateは便利ですが、どちらも「積み上げ式」であり、長期運用には向きません。
- Ridgepole はRails向けに「状態同期型」の発想を持ち込み、SchemafileでDBスキーマを一元管理できる。
- sqldef はSQLベースで言語を選ばず、Laravelをはじめ幅広い環境で使える。
両者の共通点は、「DBスキーマをコードとして宣言し、差分を自動適用する」 という思想です。
これにより、開発環境・テスト環境・本番環境を正確に揃え、リリース時の事故を防ぐことができます。
実務的結論
- 短期開発や小規模プロジェクト → 標準migrateで十分。
- 長期運用・チーム開発 → 状態同期型を導入して将来の負債を減らす。
- 異種混在チームやマイクロサービス → SQLで一元管理できるsqldefが最適。
2025年の現場感としては、RailsならRidgepole、Laravelならsqldefが半ばデファクトになりつつあります。
「未来の自分やチームを楽にできるかどうか」を基準に選ぶのが、最も実務的な判断基準でしょう。
コメント