`eager_load: true` 時に ERBTracker が登録される不具合を修正

rails/rails

eager_load: true の環境で load_defaults 8.1 を使用すると、ERB テンプレートの依存関係トラッキングに ERBTracker が登録されてしまう不具合が修正されました。原因は ActionView.render_tracker の設定タイミングにあり、ネストした after_initialize ブロックを専用の initializer に切り出すことで解消されています。

背景

Rails 8.1 では load_defaults 8.1 により config.action_view.render_tracker = :ruby がデフォルトとなり、ERB テンプレートの依存関係トラッキングに RubyTracker が使われる設計になっています(#55194)。しかし eager_load: true を設定した環境では、実際には ERBTracker が登録されるというリグレッションが #57265 として報告されていました。

問題の症状としては、config.action_view.render_trackerActionView.render_tracker の値はどちらも :ruby を返すため、設定自体は正しく見えます。しかし ActionView::DependencyTracker 内部の @trackers テーブルを確認すると、ERB ハンドラに対応するクラスが ERBTracker のままになっていました。設定値の読み取りと実際のトラッカー登録が別タイミングで行われていたことが原因です。

技術的な変更

根本原因は、ActionView.render_tracker= の呼び出しがネストした config.after_initialize ブロックの中に配置されていたことです。外側の after_initialize が実行される時点で内側のブロックが登録されますが、その内側ブロックが実際に実行されるのはすべての after_initialize コールバックが完了した後になります。eager_load: true の場合、クラスのロードが after_initialize の完了前に行われるため、DependencyTracker へのトラッカー登録が間に合わない状態が発生していました。

変更前(actionview/lib/action_view/railtie.rb):

config.after_initialize do |app|
  config.after_initialize do
    ActionView.render_tracker = config.action_view.render_tracker
  end
  # ...
end

変更後(actionview/lib/action_view/railtie.rb):

initializer "action_view.set_render_tracker" do |app|
  ActionView.render_tracker = app.config.action_view.render_tracker
end

専用の initializer "action_view.set_render_tracker" に切り出すことで、このコールバックは after_initialize よりも前のフェーズで実行されるようになり、eager_load によるクラスロードの前にトラッカー登録が完了します。

あわせて actionview/lib/action_view.rb では、singleton_class.attr_accessor :render_trackerattr_reader と明示的なセッターに分割されました。新しいセッターは値の代入と同時に DependencyTracker へのトラッカー登録を行います。

singleton_class.attr_reader :render_tracker

def self.render_tracker=(value)
  @render_tracker = value
  case value
  when :ruby
    DependencyTracker.register_tracker :erb, DependencyTracker::RubyTracker
  else
    DependencyTracker.register_tracker :erb, DependencyTracker::ERBTracker
  end
  value
end

self.render_tracker = :regex

これにより、ActionView.render_tracker= を呼び出すだけで DependencyTracker の状態が常に同期されるようになりました。また DependencyTrackereager_autoload ブロックに追加され、セッター内で参照可能な状態が保証されています。

設計判断

セッターにサイドエフェクトを持たせる設計 が採用されました。render_tracker= の呼び出し元が DependencyTracker.register_tracker を別途呼ぶ必要がなくなり、値の設定とトラッカー登録の一貫性がセッター自身によって保証されます。

attr_accessorattr_reader + カスタムセッターに置き換えたことで、将来的に :ruby / :regex 以外の値が追加された場合も、セッター内の case 文を拡張するだけで対応できる構造になっています。PR では :ruby 以外はすべて ERBTracker にフォールバックする実装が選ばれており、未知の値に対して安全なデフォルト動作を維持しています。

テスト面では actionview/test/template/dependency_tracker_test.rbrender_tracker の変更が DependencyTracker へ即座に反映されることを確認するユニットテストが、railties/test/application/configuration_test.rb には eager_load: true かつ enable_reloading: false の本番相当環境での統合テストが追加されています。

まとめ

本 PR は初期化フェーズの順序問題とセッターの副作用欠如という2つの独立した問題を同時に解消しています。initializer による実行タイミングの正規化と、セッターへのトラッカー登録ロジックの集約により、eager_load: true 環境での依存関係トラッキングの正確性が担保されました。

記事メタデータ

Generated by:
Claude Sonnet 4.6 for DiffDaily
LLM Trace:
b152d4da

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
承認済み
Review Count:
1回
Reviewed by:
Gemini 2.5 Pro for DiffDaily

Review Criteria:

記事構成 ✓ PASS

Title, Context, Technical Detailの存在と明確さ

「総論→各論→結論」の構成が明確で、リード文、背景、技術詳細、設計判断、まとめの全要素が過不足なく含まれています。

カスタムMarkdown構文 ✓ PASS

シンタックスハイライト・GitHubリンク記法の正確性

ファイル名付きコードブロックやGitHubのPR/Issueリンク記法が正しく使用されています。

対象読者への適合性 ✓ PASS

エンジニア向けの適切な技術レベルと表現

Railsの内部実装に関する専門的な内容であり、対象読者であるエンジニアに適した技術レベルで記述されています。

パラグラフ・ライティング ✓ PASS

トピックセンテンス・1段落1トピック・段落長

各セクションが総論・各論で構成され、各段落がトピックセンテンスで始まるなど、パラグラフ・ライティングの原則が遵守されており、高い可読性を実現しています。

Diff内容との照合 ✓ PASS

コードブロックとDiff内容の一致

記事内のコード引用は、提供されたDiff情報と完全に一致しており、変更点が正確に表現されています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

`initializer`, `eager_load`, `DependencyTracker`などの専門用語が文脈に沿って正確に使用されています。

説明の技術的正確性 ✓ PASS

技術的主張の正確性と論理性

初期化シーケンスのタイミング問題やセッターの副作用といった技術的な説明が、Diffの内容と整合しており、論理的かつ正確です。

事実の突合 ✓ PASS

PR情報による主張の裏付け(ハルシネーション検出)

記事内のすべての主張は、PRのDescription、Diff、または関連Issueの情報に裏付けられており、ハルシネーションは検出されませんでした。

数値・固有名詞の確認 ✓ PASS

PR番号・コミットID・バージョン等の正確性

PR番号、Issue番号、バージョン番号などの数値や固有名詞はすべて正確に記載されています。

タイトル・説明との一致 ✓ PASS

記事タイトル・説明とPR内容の一致

記事のタイトルはPRの主題「`eager_load: true`時のトラッカー登録不具合の修正」を的確に要約しています。

外部知識の正確性 ✓ PASS

PRに記載のない外部知識(LTS、サポート状況など)の不使用

PRの修正対象であるIssueで言及されている背景情報(`load_defaults 8.1`など)を適切に引用しており、PRの文脈を超える不要な外部知識の追加はありません。

時間表現の正確性 ✓ PASS

時間表現がPR情報と一致しているか

時間に関する不正確な表現や、事実を歪曲するような記述は見られませんでした。