ActiveModelオブジェクトに追加ローカル変数を渡すとドロップされる不具合を修正

rails/jbuilder

v2.15.0で発生したリグレッションを修正し、json.partial! @post, highlighted: true のようにActiveModelオブジェクトと追加ローカル変数を組み合わせた呼び出しが正しく動作するようになりました。

背景

v2.15.0で partial! メソッドに渡した追加ローカル変数が、第一引数がActiveModelオブジェクトの場合にサイレントに無視されるリグレッションが発生しました。これは #616 として報告されています。

問題の原因は、v2.15.0で取り込まれたコミット 44b42f9Remove call to one?)にあります。このコミットは args.one? のチェックを削除し、引数の数に関係なくActiveModelの分岐に入るよう変更しました。その結果、json.partial! @post, highlighted: true のような呼び出しは第二引数以降(追加ローカル変数)を無視したまま _render_active_model_partial args.first へと進むようになりました。

_render_active_model_partial は内部で @context.render object, json: self を呼ぶだけであり、追加ローカル変数を受け取る引数を持たないため、パーシャル内で highlighted を参照すると undefined local variable or method 'highlighted' エラーが発生します。

技術的な変更

修正はコミットのリバートとして、args.one? チェックを復元する1行の変更で構成されています。

変更前(v2.15.0):

def partial!(*args)
  if _is_active_model?(args.first)
    _render_active_model_partial args.first
  else
    options = args.extract_options!.dup

変更後(本PR):

def partial!(*args)
  if args.one? && _is_active_model?(args.first)
    _render_active_model_partial args.first
  else
    options = args.extract_options!.dup

args.one? を条件に加えることで、ActiveModelの高速パスはオブジェクト単体の場合にのみ適用されます。json.partial! @post, highlighted: true のように追加ローカル変数が存在する場合は args.one?false となり、else ブランチの汎用処理(extract_options! によるオプション展開)へフォールスルーします。

テストにも変更が加えられています。既存の RACER_PARTIALjson.highlighted local_assigns.fetch(:highlighted, false) が追加され、追加ローカル変数を受け取るパーシャル定義となりました。さらに、以下のテストケースが追加されています:

test "partial for Active Model preserves extra locals" do
  result = render('json.partial! @racer, highlighted: true', racer: Racer.new(123, "Chris Harris"))
  assert_equal 123, result["id"]
  assert_equal "Chris Harris", result["name"]
  assert_equal true, result["highlighted"]
end

このテストにより、ActiveModelオブジェクトと追加ローカル変数の組み合わせが今後リグレッションしないことが保証されます。

設計判断

シンプルなリバートが採用されました。 削除された args.one? チェックを元に戻すだけという最小限の変更です。

ActiveModelの高速パス(_render_active_model_partial)は、追加ローカル変数を扱う仕組みを持っていません。引数が1つだけのときに限定することで、追加ローカル変数がある場合には既存の汎用パスへ委譲する設計が維持されています。汎用パスは extract_options! でオプションHashを取り出し、パーシャルのレンダリングに渡すため、追加ローカル変数を正しく処理できます。

まとめ

本PRは1行の条件式の復元により、v2.15.0のリグレッションを解消しました。ActiveModelオブジェクトへの高速パスは「引数が1つのみの場合」という当初の意図通りの制約に戻り、追加ローカル変数を持つ呼び出しは汎用パスで正しく処理されるようになっています。

記事メタデータ

Generated by:
Claude Sonnet 4.6 for DiffDaily
LLM Trace:
981f6756

この記事は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リンク記法の正確性

ファイル名付きシンタックスハイライト、コミットIDやIssue/PR番号のリンク記法がガイドラインに沿って正しく使用されています。

対象読者への適合性 ✓ PASS

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

リグレッション、高速パス、ローカル変数といった専門用語を適切に使い、対象読者であるエンジニアに合わせたレベルで記述されています。

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

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

各セクション、各パラグラフが「総論→各論」の構造で書かれており、トピックセンテンスが明確です。非常に読みやすい構成になっています。

Diff内容との照合 ✓ PASS

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

記事内のコードスニペット(変更前・変更後、テストコード)は、提供されたDiffの内容を正確に反映しています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

ActiveModel, partial!, リバートなど、関連する技術用語が正確かつ適切な文脈で使用されています。

説明の技術的正確性 ✓ PASS

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

`args.one?` チェックの有無がなぜローカル変数の無視につながるのか、その技術的メカニズムが論理的かつ正確に説明されています。

事実の突合 ✓ PASS

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

すべての主張はPRのDescription、Diff、およびPRが修正対象とするIssueの内容に基づいており、根拠が明確です。

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

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

PR番号(#617)、Issue番号(#616)、コミットID(44b42f9)など、すべての数値・固有名詞が正確です。

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

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

記事のタイトルはPRの主題「追加ローカル変数が渡された際のActive Modelパーシャルの不具合修正」を的確に要約しています。

外部知識の正確性 ✓ PASS

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

PRに直接記載のないバージョン番号(v2.15.0)に言及していますが、これはPRが修正対象とするIssueに記載された事実であり、背景説明として適切です。不必要な外部知識の追加はありません。

時間表現の正確性 ✓ PASS

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

リグレッションの発生という過去の事象を述べており、時間表現に関する誤りや歪曲はありません。