[Rails] マイグレーション実行戦略のカスタマイズ機能に関するドキュメント整備
Context
Railsには「Swappable Migration Strategies」という機能が存在します。これは#45324で導入され、#56204でアダプタごとの戦略サポートが追加されました。Shopifyではこの機能を本番環境のマイグレーションシステムに活用していますが、Rails本体のドキュメントが不足していました。本PRではこの機能に関する包括的なドキュメントを追加しています。
Technical Detail
マイグレーション実行戦略とは
マイグレーション実行戦略は、マイグレーションとデータベース接続の間に位置するオブジェクトで、スキーマ変更がどのように適用されるかを制御します。create_table、add_columnなどのメソッド呼び出しは、マイグレーションクラスから直接接続に送られるのではなく、実行戦略を経由します。
デフォルトではActiveRecord::Migration::DefaultStrategyが使用され、すべてのメソッド呼び出しを接続アダプタに委譲します。
ExecutionStrategyクラスのドキュメント化
基底クラスExecutionStrategyに詳細なドキュメントが追加されました:
class ExecutionStrategy
def initialize(migration)
@migration = migration
end
attr_reader :migration
private
def method_missing(method, *arguments, &block)
migration.connection.send(method, *arguments, &block)
end
end
戦略は初期化時に現在のマイグレーションインスタンスを受け取り、migration属性でアクセス可能です。実装されていないメソッドはmethod_missingを通じて接続に委譲されます。
DefaultStrategyの拡張ドキュメント
DefaultStrategyは実行戦略のカスタマイズにおける推奨基底クラスです。このクラスを継承することで、特定のメソッドのみをオーバーライドしつつ、他の操作はデフォルトの動作を維持できます:
class AuditingStrategy < ActiveRecord::Migration::DefaultStrategy
def create_table(table_name, **options)
Rails.logger.info "Creating table: #{table_name}"
super
end
def drop_table(table_name, **options)
Rails.logger.warn "Dropping table: #{table_name}"
super
end
end
戦略の適用方法
カスタム戦略は2つのレベルで適用できます:
グローバル適用(すべてのアダプタ):
config.active_record.migration_strategy = AuditingStrategy
アダプタ固有の適用:
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.migration_strategy = AuditingStrategy
Active Record Migrationsガイドへの追加
新しいセクション「Customizing Migration Behavior with Swappable Strategies」がガイドに追加されました。このセクションでは以下の実用例が示されています:
本番環境でのテーブル削除防止:
class CustomMigrationStrategy < ActiveRecord::Migration::DefaultStrategy
def drop_table(table_name, **options)
raise "Dropping tables is not allowed in production!"
end
end
config.active_record.migration_strategy = CustomMigrationStrategy if Rails.env.production?
オンラインスキーマ変更ツールとの統合:
pt-online-schema-changeやgh-ostのようなツールを使用して、ダウンタイムなしでスキーマ変更を実行できます:
class OnlineSchemaChangeStrategy < ActiveRecord::Migration::DefaultStrategy
def add_column(table_name, column_name, type, **options)
# pt-online-schema-changeを使用してカラムを追加
system("pt-online-schema-change ...")
end
end
集中管理システムへのマイグレーション送信:
大規模なデプロイメントでは、マイグレーションを直接実行するのではなく、集中管理サービスに送信することが有用です。
実用的な利用シーン
この機能は以下のような場面で特に有効です:
- 安全性とバリデーション: 本番環境での危険な操作(テーブル削除、カラム削除)を防止
- オンラインスキーマ変更: ダウンタイムなしでスキーマ変更を実行するツールとの統合
- 監査とロギング: すべてのマイグレーション操作を記録
- マルチテナントシステム: テナントごとに異なるマイグレーション戦略を適用
Shopifyでは、この機能を活用して本番環境のマイグレーションシステムを実装しており、大規模なデプロイメントにおける安全性と制御を実現しています。