レガシー接続APIの廃止をRails < 7.2へバックポート
3-0-stableブランチに対し、Rails 8.xで直接呼び出しが不可となったActiveRecord::Base.connectionの廃止変更をバックポートしました。Rails < 7.2との互換性を保つため、すべての接続API切り替えはバージョン・機能検出による条件分岐で制御されています。
背景
Rails 8.xではActiveRecord::Base.connectionの直接呼び出しが例外を送出するようになり、with_connectionブロックを使った明示的な接続管理が推奨されています。この変更は元々#8883でmainブランチに取り込まれ、レガシー接続サポートの廃止とRails推奨スタイルへの統一が行われました。
3-0-stableブランチはRails < 7.2を引き続きサポートしているため、mainブランチのチェリーピック(コミットe602ef7)をそのまま適用することはできませんでした。with_connectionはRails 7.2で導入されたAPIであり、それ以前のバージョンでは存在しないからです。本PR(#8965)は、コンフリクト解消を経てこのギャップを埋めるバックポートです。
技術的な変更
接続APIの切り替えは「バージョン番号の比較」ではなく「メソッドの存在確認(respond_to?)」によるランタイム検出で実装されており、将来のRailsバージョンへの追従も自動で行われる設計になっています。
lib/active_admin/resource.rb の resource_quoted_column_name メソッドが最初の変更箇所です。
変更前:
def resource_quoted_column_name(column)
resource_class.connection.quote_column_name(column)
end
変更後:
def resource_quoted_column_name(column)
if resource_class.respond_to?(:with_connection)
resource_class.with_connection do |connection|
connection.quote_column_name(column)
end
else
resource_class.connection.quote_column_name(column)
end
end
spec/unit/resource_controller/data_access_spec.rb のテストコードも同様のパターンで修正されています。in_paginated_batchesのテスト内でActiveRecord::Base.connectionを直接参照していた箇所が、lease_connection の存在確認を経た条件分岐に置き換えられました。lease_connectionはwith_connectionと同じくRails 7.2で追加された接続リースAPIです。
connection = if ActiveRecord::Base.respond_to?(:lease_connection)
ActiveRecord::Base.lease_connection
else
ActiveRecord::Base.connection
end
expect(connection.query_cache_enabled).to be_falsy
テスト環境の設定についても、spec/support/rails_template.rb で permanent_connection_checkout = :disallowed の設定がRails 7.2以降にのみ適用されるよう条件付けられています。
# Disallow permanent connection checkout (Rails >= 7.2)
if Rails.gem_version >= Gem::Version.new("7.2.0")
environment "config.active_record.permanent_connection_checkout = :disallowed"
end
この設定により、Rails 7.2以降の環境では接続の永続チェックアウトを禁止してテストを実行し、connectionの直接呼び出しが残っていれば早期に検出できます。あわせて spec/unit/resource_spec.rb に resource_quoted_column_name の動作を検証するテストケースが追加されました。
設計判断
respond_to?によるランタイム検出を採用した点がこのバックポートの核心です。Rails.gem_versionとの比較による静的なバージョン分岐ではなく、対象メソッドの存在をその場で確認する方式を取ることで、将来的にAPIが追加・変更された場合にも条件分岐のメンテナンスが不要になります。プロダクションコード(resource.rb)ではwith_connectionの有無を、テストコード(data_access_spec.rb)ではlease_connectionの有無をそれぞれ検出しており、文脈に応じた適切なAPIを使い分けています。
一方、テスト環境のセットアップ(rails_template.rb)ではGem::Versionによる明示的なバージョン比較が使われています。これはアプリケーション起動時の設定生成フェーズで使用されるコードであり、permanent_connection_checkoutという設定キー自体がRails 7.2未満では存在しないためです。ランタイムの動的な検出が適さない文脈では静的なバージョン比較を使い、プロダクションコードとテストセットアップで検出手段を使い分けた合理的な判断といえます。
まとめ
本PRは、Rails 8.xで非推奨となった接続APIの廃止をRails < 7.2との互換性を維持しながら3-0-stableへ導入した変更です。respond_to?によるランタイム検出という共通パターンを採用することで、コードの変更箇所を最小限に抑えつつ、複数のRailsバージョンにまたがる3-0-stableブランチの継続的な健全性を確保しています。