`Date::DATE_FORMATS` の意図しない `freeze` を取り消す修正

rails/rails

Date::DATE_FORMATS に誤って適用されていた .freeze を除去し、ユーザーがカスタムフォーマットを追加できる本来の仕様を回復しました。

背景

Date::DATE_FORMATS は、ユーザーが独自のフォーマットを追加することを想定した拡張ポイントです。定数自体のコメントにも DATE_FORMATS[:month_and_year] = "%B %Y" のような追加方法が明記されており、ミュータブルであることが前提の設計となっています。

しかし、コミット 34bce3f において .freeze が意図せず付与され、カスタムフォーマットの追加時に FrozenError が発生する状態になっていました。本PRはこの意図しない変更を取り消すものです。

技術的な変更

activesupport/lib/active_support/core_ext/date/conversions.rb から .freeze を除去し、RuboCopの Style/MutableConstant 警告を抑制するコメントを追加しました。

変更前:

DATE_FORMATS = {
  short: "%d %b",
  long: "%B %d, %Y",
  ...
  iso8601: lambda { |date| date.iso8601 }
}.freeze

変更後:

DATE_FORMATS = { # rubocop:disable Style/MutableConstant
  short: "%d %b",
  long: "%B %d, %Y",
  ...
  iso8601: lambda { |date| date.iso8601 }
}

このアプローチは、activesupport/lib/active_support/core_ext/time/conversions.rbTime::DATE_FORMATS で既に採用されているパターンと統一されています。

設計判断

意図的にミュータブルな定数として維持する という判断が取られました。

RuboCopの Style/MutableConstant ルールは通常、定数の意図しない変更を防ぐために .freeze を推奨しますが、DATE_FORMATS はその例外にあたります。フォーマットの追加・上書きをユーザーに開放することがAPIの契約であるため、rubocop:disable コメントで明示的に例外として扱っています。同様の設計は Time::DATE_FORMATS にも適用されており、両定数の一貫性も回復しています。

まとめ

本PRは .freeze の一行削除と rubocop:disable コメントの追加という最小限の変更で、Date::DATE_FORMATS の拡張性を本来の仕様に戻しています。Time::DATE_FORMATS との一貫性も回復し、カスタムフォーマットを追加しているアプリケーションで発生していた FrozenError が解消されます。

記事メタデータ

Generated by:
Claude Sonnet 4.6 for DiffDaily
LLM Trace:
691ff5ba

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

品質レビュー結果

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

Review Criteria:

記事構成 ✓ PASS

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

記事全体の構成が「リード文(総論)→背景・技術詳細(各論)→まとめ(結論)」という理想的な3部構成に準拠しており、非常に分かりやすいです。

カスタムMarkdown構文 ✓ PASS

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

ファイル名付きのシンタックスハイライト(```ruby:ファイルパス)と、短縮コミットハッシュやPR番号のGitHubリンク記法が正しく使用されています。

対象読者への適合性 ✓ PASS

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

`.freeze`, `FrozenError`, RuboCopルールなど、専門知識を持つエンジニアを対象とした適切な技術レベルと語彙で書かれています。

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

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

各セクションが総論→各論の構成になっており、各段落はトピックセンテンスで始まっています。1段落1トピックの原則が守られており、可読性が高いです。

Diff内容との照合 ✓ PASS

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

Diffで示された `.freeze` の削除と `rubocop:disable` コメントの追加が、変更前後のコードブロックで正確に表現されています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

`.freeze`, `FrozenError`, `Style/MutableConstant` といった技術用語が正確かつ適切な文脈で使用されています。

説明の技術的正確性 ✓ PASS

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

「`.freeze` によって `FrozenError` が発生する」「`Time::DATE_FORMATS` との統一」といった説明は、技術的に正確で論理的です。

事実の突合 ✓ PASS

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

記事内のすべての主張(意図しない変更であること、コミット`34bce3f`が原因であること、`Time::DATE_FORMATS`の挙動に倣ったこと等)は、PRのDescriptionで完全に裏付けられています。

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

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

PR番号(#57332)、コミットID(34bce3f)といった固有名詞や数値が正確に記載されています。

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

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

記事タイトル「`Date::DATE_FORMATS` の意図しない `freeze` を取り消す修正」は、PRのタイトル「fix: unfreeze Date::DATE_FORMATS」の内容を的確に表現しています。

外部知識の正確性 ✓ PASS

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

記事で言及されているRuboCopルールや`FrozenError`は、PR内容を説明するための直接的な技術的背景であり、PRに記載のない外部知識の捏造には該当しません。バージョン情報などの不適切な外部知識の追加はありません。

時間表現の正確性 ✓ PASS

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

「〜になっていました」のように、過去の状態と今回の変更を区別する時間表現が正確に使用されています。