ActiveSupport::TimeFormats のラムダを Ractor 共有可能にする
ActiveSupport::TimeFormats が保持する日時フォーマット用ラムダを、Ractor 環境でも安全に共有できるよう変更しました。機能的な変更はなく、既存コードはそのまま動作します。
背景
Ractor はオブジェクトの安全な共有を提供しますが、標準の Proc や lambda はデフォルトで共有不可です。ActiveSupport::TimeFormats は @list ハッシュに複数のフォーマット用ラムダを保持しており、Ractor 内でこれらを参照すると Ractor::IsolationError が発生していました。既存の long_ordinal、rfc822、rfc2822、iso8601 などのキーは直接 lambda { |time| … } で定義されていました。
技術的な変更
対象となるラムダを ActiveSupport::Ractors.shareable_lambda でラップするだけの置換が行われました。変更前後のコードは以下のとおりです。
変更前:
long_ordinal: lambda { |time|
day_format = ActiveSupport::Inflector.ordinalize(time.day)
time.strftime("%B #{day_format}, %Y %H:%M")
},
rfc822: lambda { |time|
offset_format = time.formatted_offset(false)
time.strftime("%a, %d %b %Y %H:%M:%S #{offset_format}")
},
rfc2822: lambda { |time| time.rfc2822 },
iso8601: lambda { |time| time.iso8601 }
変更後:
long_ordinal: ActiveSupport::Ractors.shareable_lambda { |time|
day_format = ActiveSupport::Inflector.ordinalize(time.day)
time.strftime("%B #{day_format}, %Y %H:%M")
},
rfc822: ActiveSupport::Ractors.shareable_lambda { |time|
offset_format = time.formatted_offset(false)
time.strftime("%a, %d %b %Y %H:%M:%S #{offset_format}")
},
rfc2822: ActiveSupport::Ractors.shareable_lambda { |time| time.rfc2822 },
iso8601: ActiveSupport::Ractors.shareable_lambda { |time| time.iso8601 }
ActiveSupport::Ractors.shareable_lambda は activesupport/lib/active_support/ractors.rb に定義されており、Ruby のバージョンに応じて Ractor.shareable_lambda へ委譲するか、単にブロックを返す実装になっています。このラッパーを通すだけで、元のラムダのロジックは変わらず、Ractor で安全に共有できるようになります。
設計判断
新たな設定キーや API を追加せず、既存の @list エントリをラップすることで後方互換性を最大化しました。ActiveSupport::Ractors.shareable_lambda を中心に実装を集約することで、Ruby バージョン間の差異を内部で吸収し、Ractor の有無に関わらず同一コードベースで動作します。外部からは変更を意識する必要がなく、他モジュールへの波及効果も抑えられています。
まとめ
この PR は ActiveSupport::TimeFormats に格納された日時フォーマット用ラムダを Ractor 共有可能 に変換し、マルチスレッド環境での安全性を向上させました。振る舞いはそのままで、API 互換性も維持されているため、今後の Ractor 活用の基盤として利用できます。
- Primary Source: #57857
- Generated by: gpt-oss-120b for DiffDaily