MySQLアダプタの `NATIVE_DATABASE_TYPES` 定数のフリーズを無効化

rails/rails

#57323 で有効化された Style/MutableConstant Cop が NATIVE_DATABASE_TYPES をフリーズしたことで、この定数を拡張しているサードパーティgemが実行時エラーを起こすリグレッションが発生しました。本PRはその修正として、MySQL アダプタの NATIVE_DATABASE_TYPES に対して rubocop:disable コメントを付与してフリーズを取り除きます。

背景

#57323 は Ractor 安全性向上を目的として Style/MutableConstant Cop をリテラル定数に対して有効化した変更です。この Cop はミュータブルなリテラル(HashやArray)を定数に代入する際に .freeze を付加し、複数の Ractor 間で安全に共有できるようにします。

ただし NATIVE_DATABASE_TYPES は、フレームワーク利用者が型マッピングを拡張するために意図的にミュータブルなまま公開されている定数です。neighbor gem はMySQL向けにベクトル型を追加するため、起動時に Neighbor::MySQL.initialize! 内でこの定数を直接書き換えています。フリーズされた状態でこのコードが実行されると、以下のような FrozenError が発生してアプリケーションが起動不能になります。

can't modify frozen Hash: {...} (FrozenError)
    from neighbor-1.0.0/lib/neighbor/mysql.rb:9:in 'Neighbor::MySQL.initialize!'

このパターンはRailsが意図的に許容してきたものであり、PostgreSQLアダプタでも同様に NATIVE_DATABASE_TYPES はフリーズされていません。

技術的な変更

abstract_mysql_adapter.rbNATIVE_DATABASE_TYPES から .freeze を取り除き、代わりに # rubocop:disable Style/MutableConstant コメントを付与しました。

変更前:

NATIVE_DATABASE_TYPES = {
  primary_key: "bigint auto_increment PRIMARY KEY",
  string:      { name: "varchar", limit: 255 },
  # ...
  json:        { name: "json" },
}.freeze

変更後:

NATIVE_DATABASE_TYPES = { # rubocop:disable Style/MutableConstant
  primary_key: "bigint auto_increment PRIMARY KEY",
  string:      { name: "varchar", limit: 255 },
  # ...
  json:        { name: "json" },
}

変更はハッシュ定義の冒頭に rubocop:disable コメントを追加し、末尾の .freeze を削除する2行のみです。

設計判断

rubocop:disable コメントによる明示的な意図の記録 が選択されました。単に .freeze を削除するだけでなく、この定数がミュータブルで公開されていることをコードレベルで明示します。これはPostgreSQLアダプタの NATIVE_DATABASE_TYPES が採用している同一のアプローチと一貫しています。

Style/MutableConstant Cop を literals スタイルで有効化した #57323 の動機はRactor安全性の向上でした。しかし NATIVE_DATABASE_TYPES のようなフレームワーク拡張ポイントは、Ractor間共有よりも拡張性の確保が優先されるケースであり、Cop の適用除外が妥当な判断です。この disable コメントは、将来のコントリビュータに対して「このフリーズの欠如は意図的なものである」というシグナルを明示的に伝える役割を担います。

まとめ

この修正は Style/MutableConstant Cop の一括適用が引き起こしたリグレッションへの対処であり、「Ractor安全性のための定数フリーズ」と「フレームワーク拡張ポイントの維持」というトレードオフを明確に解決しています。rubocop:disable コメントを活用することで、機械的なルール適用と設計上の意図を共存させる手法がRails内で一貫して採用されていることが確認できます。

記事メタデータ

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

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

ファイル名付きのシンタックスハイライト、PR番号のリンク化など、カスタムMarkdown構文がガイドライン通りに正しく使用されています。

対象読者への適合性 ✓ PASS

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

`Ractor`や`Style/MutableConstant` Copなどの専門用語を前提として解説しており、対象読者であるエンジニアにとって冗長な説明がなく、適切な技術レベルで書かれています。

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

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

各セクションが総論→各論の構造を持ち、各パラグラフがトピックセンテンスで始まるため、非常に読みやすく、要点を素早く把握できます。1段落1トピックの原則も守られています。

Diff内容との照合 ✓ PASS

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

記事内のコードブロックは、提供されたDiff情報を正確に反映しています。`.freeze`の削除と`rubocop:disable`コメントの追加が正しく示されています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

`NATIVE_DATABASE_TYPES`や`FrozenError`など、関連する技術用語が文脈に沿って正確に使用されています。

説明の技術的正確性 ✓ PASS

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

リグレッションの原因、`neighbor` gemへの影響、`FrozenError`の発生メカニズムなど、技術的な説明が正確かつ論理的です。

事実の突合 ✓ PASS

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

記事内のすべての主張は、PRのDescriptionやDiffの内容に基づいており、根拠のない推測やハルシネーションは見られません。

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

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

PR番号(#57333, #57323)やファイルパスなど、すべての固有名詞と数値が正確に記載されています。

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

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

記事のタイトルはPRのタイトル「Disable freezing of NATIVE_DATABASE_TYPES for MySQL adapter」の内容を的確に要約しており、記事全体の内容とも一致しています。

外部知識の正確性 ✓ PASS

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

記事はPRで提供された情報に忠実であり、バージョンのサポート状況やリリース予定といったPR外の知識を持ち込んでいません。

時間表現の正確性 ✓ PASS

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

「〜で有効化された」といった過去の事象に関する時間表現が正確に使われており、事実関係の誤解を招く記述はありません。