`number_to_currency` が `precision: nil` の負数でクラッシュするバグを修正

rails/rails

number_to_currencyprecision: nil を指定した負の数値で TypeError を起こす不具合を、ガード条件に nil 判定を追加するだけのシンプルな修正で解消します。これにより、同様の挙動を持つ number_to_roundednumber_to_percentage と同一の呼び出し体験が提供されます。

背景

number_to_currency は正の数に対しては precision: nil(丸めなし)を受け付け、"$1,234.5678" のように小数部をそのまま出力しますが、負の数を渡すと TypeError: nil can't be coerced into Integer が発生していました。原因は負数ブランチで使用されている次のガード式です。

format = options[:negative_format] if (number_d * 10 ** options[:precision]) >= 0.5

options[:precision]nil だった場合に 10 ** nil が評価され、例外が投げられます。一方、number_to_roundednumber_to_percentage は同様のロジックで precision: nil を許容しており、負数でも正しく動作します。この不整合がユーザーに予期せぬエラーをもたらしていました。

技術的な変更

負数ブランチのガード式に options[:precision].nil? のチェックを追加し、precisionnil の場合は直接 negative_format を適用するよう変更しました。変更点は以下の通りです。

変更前:

format = options[:negative_format] if (number_d * 10**options[:precision]) >= 0.5

変更後:

format = options[:negative_format] if options[:precision].nil? || (number_d * 10**options[:precision]) >= 0.5

この1行の修正により、precisionnil の場合は丸めが行われず、負の符号はそのまま保持されます。さらに、回帰テストとして以下の3ケースを activesupport/test/number_helper_test.rb に追加しました。

assert_equal("$1,234.5678", number_helper.number_to_currency(1234.5678, precision: nil))
assert_equal("-$1,234.5678", number_helper.number_to_currency(-1234.5678, precision: nil))
assert_equal("-$1,234.5678", number_helper.number_to_currency("-1234.5678", precision: nil))

テストが全て通過し、他の数値ヘルパーメソッドとの挙動の統一が確認できました。

設計判断

今回の修正は 最小侵入 を理念とし、既存ロジックへの影響を限定的に抑える形で実装されています。負数ブランチに nil 判定を加えるだけで、positive パスと同様のフローを再利用でき、コードサイズや実行コストの増加は事実上ありません。また、precision: nil が「丸めなし」を意味するという設計意図を保ちつつ、符号保持のロジックを統一した点が評価されます。変更はバグ修正に留まり、機能追加や非互換な API 変更を伴わないため、既存利用者へのリグレッションリスクはありません。

まとめ

number_to_currencyprecision: nil の負数でクラッシュしていた根本原因は、負数ガードで 10 ** nil が評価されていたことでした。options[:precision].nil? のチェックを追加したシンプルな修正により、同様の数値ヘルパーと挙動を揃え、例外を排除しました。テスト追加により回帰が防止され、既存コードへの影響は最小限に抑えられています。

記事メタデータ

Generated by:
gpt-oss-120b for DiffDaily
LLM Trace:
1b69a788

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

品質レビュー結果

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

Review Criteria:

記事構成 ✓ PASS

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

リード文、背景、技術的変更、設計判断(任意)、まとめの5部構成が揃っており、総論→各論→結論の流れが明確です。

カスタムMarkdown構文 ⚠ WARNING

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

コードブロックは `ruby:ファイルパス` 形式で正しく記述されていますが、PRへのリンクが `[PR #57636](URL)` となっており、求められる `[ #57636 ](URL)` 形式から外れています。リンク形式を修正すればPASSになります。

対象読者への適合性 ✓ PASS

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

エンジニア向けの専門的な内容で、不要な基礎解説はなく適切です。

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

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

各セクションは総論パラグラフ→各論パラグラフ→結論パラグラフで構成され、段落は1トピック・6文未満で、トピックセンテンスが先頭に配置されています。

Diff内容との照合 ✓ PASS

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

記事内のコードブロックは提供されたDiffと完全に一致しており、変更箇所・追加テストコードとも整合しています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

`precision`, `nil`, `negative_format` などの用語が正しく使用されており、PRでの記述と一致しています。

説明の技術的正確性 ✓ PASS

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

技術的な原因・修正内容・影響について、PRの記述と矛盾なく正確に説明されています。

事実の突合 ✓ PASS

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

全ての主張がPRタイトル・説明・Diffに裏付けられており、捏造や推測はありません。

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

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

PR番号 #57636 など数値・固有名詞は正確です。

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

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

日本語タイトルはPRの要旨を正しく要約しており、内容と一致しています。

外部知識の正確性 ✓ PASS

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

バージョンやリリース情報等、PRに記載のない外部知識は含まれていません。

時間表現の正確性 ✓ PASS

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

時間表現は使用されておらず、PRと齟齬はありません。