サードパーティテンプレートハンドラのロード順問題を修正
ViewComponent 4.0へのアップグレード後、Slimなどのサードパーティテンプレートエンジンが正しく認識されない問題が修正されました。ActionView::Baseを明示的にrequireすることで、テンプレートハンドラの登録タイミングを制御し、従来の動作を復元しています。
背景
ViewComponent 4.0でViewComponent::BaseがActionView::Baseを継承しなくなったことにより、テンプレートハンドラの登録タイミングが変化しました。#2448では、eager loadが有効な環境でSlimテンプレートを持つコンポーネントに対してCouldn't find a template file or inline render methodエラーが発生する事象が報告されています。
#2409の調査により、ViewComponent::Compiler.gather_templates内でActionView::Template.template_handler_extensionsを参照する時点で、"slim"が含まれていないケースがあることが判明しました。Slimを含む多くのテンプレートエンジンは、ActionViewのロードフックを利用してテンプレートハンドラを登録します。ActionView::Baseからの継承を削除したことで、このロードフックがトリガーされるタイミングが遅れ、一部のコンポーネントがslimハンドラを認識できない状態でコンパイルされていました。
PR Descriptionによれば、ViewComponentはテンプレート検索結果をメモ化するため、後からSlimのテンプレートハンドラが登録されても、既にメモ化された「テンプレートが見つからない」という結果が使われ続けます。この仕組みが、問題を持続させる要因となっていました。
技術的な変更
lib/view_component/base.rbにrequire "action_view/base"を追加することで、ViewComponent::Baseがロードされる前にActionView::Baseが確実にロードされるようにしました。
変更内容:
require "action_view"
require "action_view/base" # 追加
require "view_component/collection"
require "view_component/compile_cache"
require "view_component/compiler"
この変更により、ActionView::Baseのロード時に登録されるロードフックがViewComponent::Baseよりも先に実行されます。結果として、SlimなどのテンプレートエンジンはViewComponent::Compiler.gather_templatesがActionView::Template.template_handler_extensionsを参照する前にハンドラを登録できるようになります。
従来の動作との互換性:
ViewComponent::BaseがActionView::Baseを継承していた時期は、継承関係によりaction_view/baseが暗黙的にrequireされていました。明示的なrequire文の追加は、この従来の動作を再現するものであり、副作用は発生しません。
設計判断
最小限の変更でロード順を制御するアプローチが採用されました。
PR Descriptionでは、この修正が「really simple」であり、「no negative side-effects」であることが強調されています。ActionView::Baseの明示的なrequireは、継承関係が存在していた時期の動作を再現するため、フレームワークの依存関係を明確にし、ロード順に依存する問題を防ぐという点でも理にかなった判断です。
継承関係の削除は#2409で指摘されているように、ロードフックのトリガータイミングに影響を与えます。今回の修正は、継承を維持せずにロードフックの実行タイミングを保証する方法として、依存関係の明示化という原則に従っています。
まとめ
本PRは、ActionView::Baseの明示的なrequireにより、ViewComponent 4.0で発生したテンプレートハンドラのロード順問題を解決しました。1行の追加で従来の動作を復元し、Slimをはじめとするサードパーティテンプレートエンジンとの互換性を回復させています。この修正は、フレームワークの依存関係を明確にし、ロード順に起因する問題を防ぐという設計原則に沿った変更といえます。