`ActiveRecord::Base.connection` の直接呼び出しを `with_connection` に移行
ActiveAdminが ActiveRecord::Base.connection の直接使用を廃止し、with_connection ブロックへ置き換えました。これにより、permanent_connection_checkout = :disallowed 設定を使用している環境でのエラーが解消されます。
背景
Rails 7.2以降で導入された config.active_record.permanent_connection_checkout 設定により、ActiveRecord::Base.connection の直接呼び出しを制御できるようになりました。この設定を :disallowed にすると、コネクションプールからのコネクションを恒久的にチェックアウトするコードを検出・排除できます。
Fiberベースの環境(非同期処理など)では、スレッド数よりもはるかに多くのFiberが存在する可能性があります。この状況で ActiveRecord::Base.connection を使用すると、コネクションプールが枯渇するリスクがあります。そのため :disallowed 設定はFiberを多用するアプリケーションで推奨されますが、ActiveAdminはこの設定と非互換でした(#8881)。
具体的には permanent_connection_checkout = :disallowed を設定した状態で管理画面にアクセスすると、以下のエラーが発生していました:
ActiveRecord::ActiveRecordError in Admin::CommentsController#index
Called deprecated `ActiveRecord::Base.connection` method.
Either use `with_connection` or `lease_connection`.
Rails 8.xではこの呼び出しが例外を発生させるようになったため、対応が必須となっていました。
技術的な変更
lib/active_admin/resource.rb の resource_quoted_column_name メソッドが、with_connection ブロック形式に変更されました。
変更前:
def resource_quoted_column_name(column)
resource_class.connection.quote_column_name(column)
end
変更後:
def resource_quoted_column_name(column)
resource_class.with_connection do |connection|
connection.quote_column_name(column)
end
end
テスト側でも対応が行われています。spec/unit/resource_controller/data_access_spec.rb では、クエリキャッシュの状態を検査する箇所で ActiveRecord::Base.connection から ActiveRecord::Base.lease_connection に変更されました。lease_connection はコネクションを一時的に借用する明示的なAPIで、テストコンテキストでの使用に適しています。
さらに spec/support/rails_template.rb に config.active_record.permanent_connection_checkout = :disallowed が追加され、テストスイート自体がこの制約下で実行されるようになりました。これにより、同様の問題が再発した場合にCI上で検出できます。
設計判断
with_connection ブロック方式 を採用することで、コネクションのスコープが明示的になります。with_connection はブロックの実行中のみコネクションをチェックアウトし、ブロック終了後にプールへ返却します。これに対し、従来の connection はリクエストやジョブの終了まで保持し続ける挙動でした。
Railsが参照先として示す rails/rails#51349 では、connection による恒久チェックアウトがFiber環境での問題の根源であることが説明されています。with_connection への移行はRailsの推奨ガイドラインに沿う判断であり、将来のRailsバージョンとの互換性を維持するうえでも合理的な選択です。
テストテンプレートへの :disallowed 設定の追加は、リグレッション防止の仕組みを組み込む判断として注目できます。修正が正しく動作することを確認するだけでなく、今後の変更で同じ問題が再発しないよう、CI環境を厳格な制約下に置いています。
まとめ
本PRはActiveAdminが抱えていたコネクション管理の非互換を、with_connection への移行という最小限の変更で解消しています。テストスイートに :disallowed 設定を組み込んだことで、同種の問題を継続的に検出できる体制が整い、Rails 8.x以降との長期的な互換性が確保されました。