safe_join のデフォルト区切り文字から $, を除去して nil に変更

rails/rails

Rails の safe_join がデフォルトで使用していた $,(Ruby のグローバル変数)を廃止し、デフォルトを nil に変更しました。これにより、Ractor 環境での安全性が向上し、未文書化の挙動がなくなります。

背景

safe_join は文字列配列を HTML 安全に結合するユーティリティで、従来は第2引数 sep のデフォルト値に $, を採用していました。実装上は sep = ERB::Util.unwrapped_html_escape(sep) でエスケープし、join(sep) で結合しているため、デフォルトの $, が区切り文字として出力されていました。

$, は Ruby 本体で 10 年以上前に非推奨化され、Ractor では完全に非安全とされています。さらに Rails の公式ドキュメントでも safe_join のデフォルトセパレータは言及されておらず、実質的に暗黙の仕様に過ぎませんでした。

このような未文書化かつ非推奨の振る舞いを残すことは、開発者に予期せぬ警告やランタイムエラーを招くリスクがあります。したがって、デフォルトから $, を除去し、Ruby が返す既定値 nil をそのまま利用する方針が取られました。

技術的な変更

safe_join のメソッドシグネチャが def safe_join(array, sep = $,) から def safe_join(array, sep = nil) へ変更され、デフォルト引数が nil となりました。これにより、呼び出し側がセパレータを省略した場合は区切り文字が付与されません。

@@
-      def safe_join(array, sep = $,)
+      def safe_join(array, sep = nil)
         sep = ERB::Util.unwrapped_html_escape(sep)

         array.flatten.map! { |i| ERB::Util.unwrapped_html_escape(i) }.join(sep).html_safe

テストコードでも $, に依存したケースが削除され、safe_join の既定動作が nil になることを検証するテストが残されています。加えて、to_sentence メソッドが内部で safe_join を呼び出す際に $, の影響を受けないことを確認するテストが追加されました。

この変更は ActionView の公開 API に対する互換性を保ちつつ、デフォルト引数の振る舞いだけを明示的に変更しています。既存コードで明示的にセパレータを渡している箇所は影響を受けません。

設計判断

$, の非推奨化は Ruby 側で長らく行われているため、Rails が独自にデプリケーションサイクルを設ける必要はなく、即時にデフォルトを削除する方針が採用されました。未文書化の挙動を残すことは API の一貫性を損ねるため、ドキュメントと実装を合わせて整理する判断が下されました。

デフォルトを nil としたことで、safe_join の呼び出し側は「区切り文字が不要」か「明示的に指定」かをはっきり表現できます。これは Ruby の標準的な Array#join の振る舞いと一致し、学習コストの低減にも寄与します。

結果として、Ractor 安全性の確保と API の明瞭化が同時に実現され、将来的なメンテナンス負荷が減少します。

まとめ

この PR は safe_join のデフォルトセパレータから $, を除去し、Ruby の既定値 nil を採用した変更です。未文書化かつ非推奨の挙動を即時に廃止することで、Ractor 環境での安全性と API の一貫性が向上します。

記事メタデータ

Generated by:
gpt-oss-120b for DiffDaily
LLM Trace:
307c64b9

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

品質レビュー結果

Review Status:
承認済み
Review Count:
1回
Reviewed by:
gpt-oss-120b for DiffDaily

Review Criteria:

記事構成 ✓ PASS

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

リード文がタイトル直下にあり、背景・技術的変更・設計判断・まとめの各セクションが揃っているため、総論→各論→結論の構成が明確です。

カスタムMarkdown構文 ⚠ WARNING

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

コードブロックは正しい `ruby:ファイルパス` 形式ですが、PRリンクが `[PR #57844](URL)` となっており、仕様の `[#123](URL)` 形式と完全には一致していません。

対象読者への適合性 ✓ PASS

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

Rails の内部実装に関する説明で、エンジニア向けの適切な技術レベルです。初心者向けの冗長な解説はありません。

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

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

各セクションが総論・各論・結論の段落構成になっており、段落はトピックセンテンスで始まり 1 段落 1 トピック、長さも適切です。空行で区切られています。

Diff内容との照合 ✓ PASS

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

記事中のコードブロックは Diff の内容と完全に一致し、削除・追加が正しく示されています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

`safe_join`、`sep`、`$,`、`nil`、Ractor などの用語は PR で使用されている通り正しく記述されています。

説明の技術的正確性 ✓ PASS

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

技術的主張は PR の背景・目的・変更点と整合性が取れており、誤った説明はありません。

事実の突合 ✓ PASS

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

記事の主張はすべて PR の記述や Diff から裏付けられており、根拠のない数値や外部知識の付加はありません。

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

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

PR 番号 #57844 が正しく記載されており、その他数値的誤りは見当たりません。

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

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

記事タイトルは PR の内容「Remove the use of `$,` as a default value for `safe_join`」を日本語で適切に表現しています。

外部知識の正確性 ✓ PASS

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

バージョンサポート状況やリリース日程等、PR に記載されていない外部知識は含まれていません。

時間表現の正確性 ✓ PASS

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

時間表現の歪曲はなく、PR の記述と一致しています。