`ActiveModel::Conversion#render_in` のデフォルト実装を一時的に差し戻し
#57349 で追加された ActiveModel::Conversion#render_in のデフォルト実装が、未リリースの段階で発覚したエッジケースを理由に差し戻されました。再設計後に改めて取り込む方針です。
背景
元のPR #57349 は、ActiveModel::Conversion にデフォルトの #render_in 実装を追加し、モデルインスタンスをビューパーシャルに直接渡してレンダリングできるようにするものでした。この実装により、render person や render renderable: person といった呼び出しが to_partial_path を経由してパーシャルへ委譲される挙動が提供されます。
しかし、マージ後のコメント(#57349のコメント)で重大なエッジケースが指摘されました。コントローラーベースのビューパーシャル名前空間(controller-based view partial namespacing) がレンダリングコンテキストに基づいて適用されない、という問題です。
ActiveModel::Conversion#render_in はまだリリースされていないため、後方互換性を壊さずに差し戻しが可能でした。本PRはその差し戻しを実施し、エッジケースに対応した改訂版PRを改めて提出する方針を取っています。
技術的な変更
本PRは 241f2a0 を完全に差し戻すものです。変更は複数のファイルにわたります。
activemodel/lib/active_model/conversion.rb から、以下の render_in メソッドが削除されました。
def render_in(view_context, **options, &block)
options.delete(:object)
view_context.render(partial: to_partial_path, object: self, **options, &block)
end
あわせて、activemodel/lib/active_model/lint.rb から test_render_in テストメソッドが削除され、render_in への応答と文字列返却を検証するリントチェックも取り除かれています。テストファイルについては、activemodel/test/cases/conversion_test.rb から #render_in の挙動を検証する2つのテストケース(デフォルト動作の検証、呼び出し元指定の :object が無視されることの検証)が削除されました。
Action View 側では、actionview/test/actionpack/controller/render_test.rb の renderable_hash コントローラアクションとその対応テストが削除されています。また、actionview/test/template/log_subscriber_test.rb では、render_in 経由のレンダリングで発生していた追加のデバッグログ出力(Rendering Customer ログ)が除去されたことにより、期待ログ件数のアサーションが 2 から 1 に修正されています。
ドキュメントとしては、activemodel/CHANGELOG.md から #render_in 追加に関するエントリが、guides/source/active_model_basics.md から render_in の使用例を示すセクションがそれぞれ削除されました。
設計判断
未リリースであることを理由に差し戻す判断 がされた点が重要です。ActiveModel::Conversion#render_in がまだどのRailsリリースにも含まれていないため、差し戻しによって既存アプリケーションへの影響はゼロです。この前提がなければ、後方互換性の問題から差し戻しではなくパッチ対応が選ばれた可能性があります。
問題の本質は、render_in の実装が view_context.render を直接呼び出す際に、コントローラーのネームスペースに基づいてパーシャルパスを解決する仕組みを持たない点にあります。Railsのパーシャルレンダリングは、呼び出しコンテキスト(どのコントローラーから呼ばれるか)に応じてパスを解釈する場合があり、この挙動を ActiveModel 層の汎用実装として正しく再現するには、追加の設計が必要です。差し戻しとして実装を完全に取り除き、改訂版PR での再提出を選んだことは、中途半端な状態をリリースしないための判断です。
まとめ
本PRは機能追加の取り消しですが、「未リリースであればクリーンに差し戻せる」というリリースサイクルを活かした現実的な対応といえます。コントローラーベースの名前空間という具体的なエッジケースを特定した上で差し戻しを行っており、改訂版PRでの正確な再設計に向けた地ならしとなっています。