Inflection ルールを起動後にフリーズして Ractor 共有可能化

rails/rails

Rails アプリケーションが起動した後でも Inflector の変化ルールを変更できる点を解消し、全てのインスタンスをフリーズして Ractor で安全に共有できるようになりました。

背景

アプリケーション起動後に inflection ルール がミュート可能であることは、テーブル名やクラス名の自動変換が実行時に予期せぬ形で変化し、デバッグが困難になるリスクを伴います。加えて、Ractor が導入された環境では、オブジェクトが共有可能であることがスレッド間安全性の前提となりますが、ミュータブルな inflection インスタンスはその前提を満たしませんでした。この背景から、起動後の変更を防止しつつ Ractor でも利用できる設計が求められました。

技術的な変更

ActiveSupport::Inflector::Inflections クラスに freeze メソッド が追加され、インスタンス内部のルール配列と正規表現パターンをすべて凍結します。フリーズ処理は次の手順で実行されます。

def freeze
  build_pattern
  @members.each(&:freeze)
  @members.freeze
  @pattern.freeze
  super
end

パターン生成は新たに導入されたプライベートメソッド build_pattern が担当し、@members から正規表現を組み立てて @pattern に設定します。

private
  def build_pattern
    members_pattern = Regexp.union(@members.map { |w| /#{Regexp.escape(w)}/i })
    @pattern = /\b#{members_pattern}\Z/i
  end

さらに、全ロケールのインスタンスを取得できるクラスメソッド all_instances が追加され、既存の instance メソッドに加えてすべてのインスタンスを列挙可能にしました。

def self.all_instances # :nodoc:
  [@__en_instance__] + @__instance__.values
end

Rails::Railtie に新しい initializer active_support.freeze_inflections が導入され、config.after_initialize フック内で Inflections.all_instances.each(&:freeze) が呼び出されます。これにより、アプリケーションが完全に起動したタイミングで全インスタンスがフリーズされます。

initializer "active_support.freeze_inflections" do
  config.after_initialize do
    ActiveSupport::Inflector::Inflections.all_instances.each(&:freeze)
  end
end

テストでは、起動後に Inflections.all_instances が Ractor 共有可能かどうかを確認し、さらにフリーズされたインスタンスに対して変更を試みると FrozenError が発生することが検証されています。

設計判断

ミュータブルな inflection ルール自体は残しつつ、フリーズ によって変更を禁止する方針が採用されました。このアプローチは既存の Inflector.inflections API をそのまま維持でき、呼び出し側のコード改修を不要にします。全インスタンスを一括でフリーズするために after_initialize フックを利用した点は、ロケールごとのインスタンス生成タイミングに依存せず確実に対象を網羅できる設計的利点があります。

まとめ

起動後の inflection ルール変更を防止し、全インスタンスをフリーズすることで Ractor 環境でも安全に共有できるようになりました。変更は Inflections クラスに限定されたメソッド追加と Railtie の初期化子追加のみで、既存コードへの影響は最小限です。

記事メタデータ

Generated by:
gpt-oss-120b for DiffDaily
LLM Trace:
9c13925a

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

品質レビュー結果

Review Status:
リトライ後承認
Review Count:
2回 (改善を経て承認)
Reviewed by:
gpt-oss-120b for DiffDaily

Review Criteria:

記事構成 ✓ PASS

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

リード文、背景、技術的な変更、設計判断、まとめの全てが揃っており、総論→各論→結論の流れが明確です。

カスタムMarkdown構文 ⚠ WARNING

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

コードブロックは正しい `言語:ファイルパス` 形式です。ただし PR リンクの表記が `[PR #57922](URL)` となっており、推奨の `[#57922](URL)` 形式と若干異なります。機能的には問題ありませんが、形式統一のために修正が望まれます。

対象読者への適合性 ✓ PASS

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

エンジニア向けに専門用語や実装詳細が記述されており、初心者向けの過剰な説明はありません。

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

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

各段落はトピックセンテンスで始まり、1段落1トピックで構成されています。文数も適切で、段落間は空行で区切られています。

Diff内容との照合 ✓ PASS

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

記事中のコードブロックは Diff に示された変更と完全に一致しています。ファイル名・コード内容ともに正確です。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

Inflector、Ractor、freeze などの用語は正しく使用されており、誤用は見られません。

説明の技術的正確性 ✓ PASS

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

技術的な説明は Diff と PR の記述に基づいており、因果関係も論理的です。

事実の突合 ✓ PASS

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

すべての主張が PR のタイトル・説明・Diff に裏付けられており、ハルシネーションはありません。

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

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

PR 番号 #57922 のみが記載されており、正確です。

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

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

記事タイトルは PR タイトル「Freeze the inflection rules after the app boots」の意味を日本語で適切に表現しています。

外部知識の正確性 ✓ PASS

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

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

時間表現の正確性 ✓ PASS

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

時間表現は「起動後」程度で、PR の記述と一致しています。