Normalization.normalizes を Ractor セーフに

rails/rails

ActiveModel の属性正規化で使用される normalized_attributes が Ractor 間で安全に共有できるようになり、振る舞いを変えずにマルチプロセス実行環境への適合性が向上します。

背景

属性正規化は Normalization モジュールの normalized_attributes に属性名を保持し、バリデーション時に参照されます。 Ractor ではオブジェクトが shareable である必要があり、ミュータブルな Set は共有できません。そのため、Ractor 環境で正規化属性を使用すると Ractor::IsolationError が発生する可能性がありました。PR はこのリスクを排除し、既存の API を保ちつつ安全性を確保することを目的としています。

技術的な変更

class_attribute :normalized_attributes のデフォルト値を凍結した Set に変更しました。 初期化時点で不変オブジェクトとなり、Ractor が直接参照できるようになります。

-        class_attribute :normalized_attributes, default: Set.new
+        class_attribute :normalized_attributes, default: Set.new.freeze

normalizes メソッド内で属性名を追加するロジックを変更し、コピー後に凍結した新しい Set を代入します。 これにより、既存の集合はミュータブルなまま残らず、常に凍結されたインスタンスが保持されます。

-          self.normalized_attributes += names.map(&:to_sym)
+          self.normalized_attributes = (normalized_attributes + names.map(&:to_sym)).freeze

テストスイートに Ractor 安全性を検証するケースを追加しました。 ActiveSupport::Testing::RactorsAssertions をインクルードし、assert_ractor_shareable マクロで normalized_attributes が共有可能であることを確認します。

@@ -1,8 +1,11 @@
 # frozen_string_literal: true

 require "cases/helper"
+require "active_support/testing/ractors_assertions"

 class NormalizedAttributeTest < ActiveModel::TestCase
+  include ActiveSupport::Testing::RactorsAssertions
@@
   test ".normalized_attributes is ractor safe" do
     assert_ractor_shareable NormalizedAircraft.normalized_attributes
   end
 end

設計判断

freeze を利用して不変オブジェクトを作成し、Ractor での共有を実現しています。 変更は normalized_attributes の生成と更新時にのみ行われ、既存コードからの呼び出し方法や戻り値の型は変わりません。ミュータブルな集合を直接保持しないことで、Ractor の安全性要件を満たす設計となっています。

属性集合の更新は新しいインスタンスを生成して代入する方式を採用しています。 これにより、読み取り側は常に凍結されたオブジェクトを取得し、書き込み側だけが新しい集合を作成します。結果として、振る舞いの変更はなく、Ractor 環境での例外が防止されます。

まとめ

Normalization.normalizes の実装が Ractor セーフとなり、normalized_attributes が不変かつ共有可能になることで、マルチプロセス環境でも属性正規化が安全に動作します。既存 API と挙動は維持されるため、利用者への影響はありません。

記事メタデータ

Generated by:
gpt-oss-120b for DiffDaily
LLM Trace:
136e8609

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

品質レビュー結果

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

Review Criteria:

記事構成 ✓ PASS

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

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

カスタムMarkdown構文 ✓ PASS

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

コードブロックは `ruby:ファイルパス` 形式で正しく記述され、PRリンクも `[#57978](URL)` で正しくリンク化されています。

対象読者への適合性 ✓ PASS

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

専門エンジニア向けの技術的記述で、初心者向けの過度な説明はありません。

パラグラフ・ライティング ⚠ WARNING

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

各セクションは総論パラグラフがあるものの、技術的変更や設計判断セクションに明確な結論パラグラフが欠けています。段落はトピックセンテンスで始まり、長さも適切ですが、セクションごとのまとめが欲しいです。

Diff内容との照合 ✓ PASS

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

記事中のコードブロックは Diff の内容と完全に一致し、ファイル名・変更点とも合致しています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

Ractor、freeze、Set などの用語が正確に使用されており、PR の記述と一致しています。

説明の技術的正確性 ✓ PASS

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

技術的な主張は Diff と PR の説明に裏付けられており、誤りはありません。

事実の突合 ✓ PASS

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

記事の全ての主張は PR タイトル、説明、Diff に基づいており、捏造や推測は見られません。

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

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

PR 番号 #57978 が正しく記載されており、他の数値や固有名詞の誤りはありません。

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

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

記事タイトルは PR タイトルの意味を日本語で正確に表現しています。

外部知識の正確性 ✓ PASS

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

外部知識(バージョンサポート等)は一切記載されておらず、PR に基づく内容のみです。

時間表現の正確性 ✓ PASS

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

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