`render?` が false のとき `render_in` が html_safe な文字列を返すよう修正

viewcomponent/view_component

render?false を返すコンポーネントを他の SafeBuffer 文字列と連結すると TypeError が発生していた問題が修正されました。render_in の非レンダリングパスが "".html_safe を返すようになり、レンダリングパスとの一貫性が保たれます。

背景

render_in の正常パスと非レンダリングパスで戻り値の型が一致していないことが問題の根本原因でした。Railsのビュー層では、render などのヘルパーが返す文字列は ActiveSupport::SafeBufferhtml_safe な文字列)であることが前提とされています。render_in の正常パス(コンポーネントが実際にレンダリングされる場合)はこの前提を満たしていましたが、render?false を返すパスは通常の String を返していました。

その結果、render(MyComponent.new) + some_helper_returning_html のようにコンポーネントの出力と他のヘルパーの出力を連結するコードで TypeError が発生していました。SafeBuffer への + 演算は相手が html_safe でない文字列だとエスケープ処理を挟むため、内部で型の不整合が生じます。

技術的な変更

変更箇所は lib/view_component/base.rbrender_in メソッド内、render?false のときの分岐の1行のみです。

変更前:

else
  ""
end

変更後:

else
  "".html_safe
end

あわせて test/sandbox/test/rendering_test.rb に、render?false のコンポーネントをレンダリングしたとき @rendered_contenthtml_safe? であることを確認するテストが追加されています。

def test_render_in_returns_html_safe_string_when_render_is_false
  render_inline(ConditionalRenderComponent.new(should_render: false))

  assert_predicate @rendered_content, :html_safe?
end

テストでは既存の ConditionalRenderComponent を再利用しており、新たなテスト用コンポーネントの追加は不要です。

設計判断

戻り値の型を常に SafeBuffer に統一するという方針が採られています。render_in の利用者はレンダリングの成否にかかわらず html_safe な文字列を受け取れるという契約が明示されたことになります。

空文字列に .html_safe を付与するだけの最小限の修正にとどめている点も注目できます。render?false のケースで返す値の意味(「何も出力しない」)は変わらず、表現の型だけを正規化しています。これにより、呼び出し側が戻り値に対して html_safe? チェックや条件分岐を追加する必要がなくなります。

まとめ

1行の修正ですが、render_in の全パスで戻り値の型契約が統一されたことで、コンポーネントの出力をビューヘルパーの結果と自由に連結できるようになります。render? による条件付きレンダリングを多用するコードベースで潜在的に発生していた TypeError が根本から解消されます。

記事メタデータ

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

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

ファイル名付きシンタックスハイライトやPR番号へのリンク記法が正しく使用されています。

対象読者への適合性 ✓ PASS

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

専門知識を持つエンジニアを対象としており、過度な説明がなく、適切な技術レベルで記述されています。

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

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

各セクションが「総論→各論」で構成され、各段落がトピックセンテンスで始まるなど、パラグラフ・ライティングの原則が守られており、非常に読みやすいです。

Diff内容との照合 ✓ PASS

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

記事内で引用されているコードブロックは、提供されたDiffの内容を正確に反映しています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

`render_in`, `SafeBuffer`, `html_safe`, `TypeError` などの技術用語が文脈に沿って正確に使用されています。

説明の技術的正確性 ✓ PASS

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

変更の理由(TypeErrorの発生)と解決策(戻り値の型統一)に関する説明は技術的に正確で、論理的です。

事実の突合 ✓ PASS

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

記事内のすべての主張は、PRのDescriptionやDiff内のコードで裏付けられています。「設計判断」セクションはコードの意図を汲んだ妥当な解説であり、ハルシネーションは認められません。

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

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

PR番号(#2584)やファイル名が正確に記載されています。

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

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

記事のタイトルは、PRのタイトルと内容を的確に要約しています。

外部知識の正確性 ✓ PASS

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

PR情報に記載のない外部知識(バージョン情報、リリース予定など)の追加はなく、事実に基づいています。

時間表現の正確性 ✓ PASS

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

「〜問題が修正されました」といった時間表現は、PRがマージ済みである事実と一致しており正確です。