AttributeMethods を Ractor セーフにするための凍結化と初期化変更

rails/rails

この PR は AttributeMethods.aliases_by_attribute_name.attribute_aliases.attribute_method_patterns を Ractor 間で安全に共有できるよう、デフォルト値を凍結し継承時に初期化する変更を導入します。従来の遅延初期化と可変オブジェクトに伴う共有リスクを排除し、振る舞いを保ったままマルチスレッド実行環境への適合性を高めます。

背景

AttributeMethods の内部キャッシュである aliases_by_attribute_nameattribute_aliasesattribute_method_patterns はデフォルトで可変なハッシュや配列を保持しており、Ractor に渡すと共有不可能になる問題がありました。Ractor 安全性を求める Rails コアでは、これらのデータ構造を凍結し、遅延評価を排除して早期に安全な状態で設定する方針が取られました。テストでも assert_ractor_shareable が失敗していたことが変更の直接的な動機です。

技術的な変更

EMPTY_HASHHash.new([].freeze).freeze として定義し、@aliases_by_attribute_name の初期値に使用することで、デフォルトの空ハッシュ自体が共有可能な状態になります。

EMPTY_HASH = Hash.new([].freeze).freeze # :nodoc:

attribute_aliasesattribute_method_patternsclass_attribute 定義に freeze を付与し、デフォルトオブジェクトが変更不可になるようにしました。また、@aliases_by_attribute_name を継承時に EMPTY_HASH で初期化し、遅延評価用の default_proc を廃止しています。

class_attribute :attribute_aliases, instance_writer: false, default: {}.freeze
@aliases_by_attribute_name = EMPTY_HASH
class_attribute :attribute_method_patterns, instance_writer: false, default: [ClassMethods::AttributeMethodPattern.new].freeze

各属性メソッドの追加ロジック(attribute_method_prefixattribute_method_suffixattribute_method_affix)は、配列操作後に結果を freeze して再代入する形に変更され、可変配列が残らないようにしました。

prefixes.map! { |prefix| AttributeMethodPattern.new(prefix: prefix, parameters: parameters) }
self.attribute_method_patterns = (attribute_method_patterns + prefixes).freeze

テストコードは ActiveSupport::Testing::RactorsAssertions をインクルードし、assert_ractor_shareable で新しいデータ構造が Ractor で共有可能であることを検証しています。

require "active_support/testing/ractors_assertions"
...
include ActiveSupport::Testing::RactorsAssertions
...
assert_ractor_shareable model.aliases_by_attribute_name
assert_ractor_shareable model.attribute_aliases
assert_ractor_shareable model.attribute_method_patterns

ActiveRecord のテストでも、attribute_method_patterns のリセット処理が attribute_method_patterns = @old_matchers とシンプルに置き換えられ、同様に凍結された配列を再代入しています。

設計判断

AttributeMethods の公開 API を変更せずに、内部キャッシュを凍結オブジェクトへ置き換える方針が採用されました。新しい設定キーやメソッドは導入せず、既存の attribute_method_patterns 配列をそのまま凍結して再代入することで、後方互換性を保ちつつ Ractor 共有可能にしました。遅延初期化を継承時に前倒しした点は、Ractor 境界での不変性を保証するための最小限の侵入的変更です。

まとめ

本変更により、aliases_by_attribute_nameattribute_aliasesattribute_method_patterns がデフォルトで凍結され、Ractor 間で安全に共有できるようになりました。振る舞いは従来と変わらず、シングルスレッド環境でも同様に動作しますが、マルチスレッド/Ractor 環境での安全性が向上し、将来的な並行実行の拡張基盤が整備されました。

記事メタデータ

Generated by:
gpt-oss-120b for DiffDaily
LLM Trace:
85e181f8

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

品質レビュー結果

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

Review Criteria:

記事構成 ✓ PASS

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

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

カスタムMarkdown構文 ⚠ WARNING

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

コードブロックのファイル名付きハイライトは正しい形式です。PR リンクは "PR #57917" という記述で、完全に指定された "[#123]" 形式ではありませんが、理解に支障はありません。

対象読者への適合性 ✓ PASS

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

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

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

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

各セクションが総論・各論・結論の段落構成になっており、トピックセンテンスで始まり、1段落1トピック、長さも適切です。空行で区切られています。

Diff内容との照合 ✓ PASS

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

記事内のコードブロックは Diff に記載された変更と正確に一致しており、抜けや誤りはありません。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

Ractor、class_attribute、freeze などの用語が正しく使用され、PR の記述と合致しています。

説明の技術的正確性 ✓ PASS

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

変更理由や実装内容、テスト追加の説明が Diff と PR の情報に基づき正確に記述されています。

事実の突合 ✓ PASS

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

記事の主張はすべて PR のタイトル・Description・Diff で裏付けられており、捏造や推測はありません。

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

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

PR 番号 #57917 以外の数値・固有名詞の誤りはありません。

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

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

記事タイトルは PR の内容を適切に日本語化しており、主旨にずれはありません。

外部知識の正確性 ✓ PASS

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

外部のバージョンサポート情報やベンチマーク結果など、PR に存在しない情報は含まれていません。

時間表現の正確性 ✓ PASS

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

時間表現は使用されておらず、矛盾はありません。