shareable_lambda の記述をブロック形式へ統一
ActionPack と ActiveSupport で使用されている ActiveSupport::Ractors.shareable_lambda の定義が、&-> 形式から標準的なブロックリテラルへ置き換えられ、可読性が向上しました。振る舞いは変わりません。
背景
Rails の内部実装では Ractor 共有可能なラムダを定数化するために **ActiveSupport::Ractors.shareable_lambda が多数使用されています**。action_controller/metal.rb、action_dispatch/http/parameters.rb、journey/visitors.rb など複数のファイルで &-> 形式が採用されていました。&-> は Ruby の一般的な記法ではなく、読者に余計な認知負荷を与えていました。
PR #57859 はこれらの定義を統一的なブロック形式に書き換えることを目的としています。PR の説明では「見た目が分かりにくい」定義を「シンプルなブロックリテラルへ」統一すると述べられています。変更はコードの見た目をシンプルにし、レビュー時の理解コストを下げることが狙いです。
技術的な変更
action_controller/metal.rb の INCLUDE、EXCLUDE、NULL 定数がブロックリテラルへ変更されました。
- INCLUDE = ActiveSupport::Ractors.shareable_lambda(&->(list, action) { list.include? action })
- EXCLUDE = ActiveSupport::Ractors.shareable_lambda(&->(list, action) { !list.include? action })
- NULL = ActiveSupport::Ractors.shareable_lambda(&->(list, action) { true })
+ INCLUDE = ActiveSupport::Ractors.shareable_lambda { |list, action| list.include? action }
+ EXCLUDE = ActiveSupport::Ractors.shareable_lambda { |list, action| !list.include? action }
+ NULL = ActiveSupport::Ractors.shareable_lambda { |list, action| true }
引数とロジックは変更前後で同一であり、挙動は変わりません。
action_dispatch/http/parameters.rb の JSON パーサ定義がブロックリテラルへ置換されました。
- Mime[:json].symbol => ActiveSupport::Ractors.shareable_lambda(&-> (raw_post) {
+ Mime[:json].symbol => ActiveSupport::Ractors.shareable_lambda do |raw_post|
data = ActiveSupport::JSON.decode(raw_post)
data.is_a?(Hash) ? data : { _json: data }
- })
+ end
JSON 解析のロジックはそのままで、記法だけが変更されています。
journey/visitors.rb のエスケープ定数がブロック形式に統一されました。
- ESCAPE_PATH = ActiveSupport::Ractors.shareable_lambda(&->(value) { Router::Utils.escape_path(value) })
- ESCAPE_SEGMENT = ActiveSupport::Ractors.shareable_lambda(&->(value) { Router::Utils.escape_segment(value) })
+ ESCAPE_PATH = ActiveSupport::Ractors.shareable_lambda { |value| Router::Utils.escape_path(value) }
+ ESCAPE_SEGMENT = ActiveSupport::Ractors.shareable_lambda { |value| Router::Utils.escape_segment(value) }
エスケープ処理自体は変更されていません。
routing/mapper.rb の制約評価用ラムダがブロックリテラルへ変更されました。
- SERVE = ActiveSupport::Ractors.shareable_lambda(&->(app, req) { app.serve req })
- CALL = ActiveSupport::Ractors.shareable_lambda(&->(app, req) { app.call req.env })
+ SERVE = ActiveSupport::Ractors.shareable_lambda { |app, req| app.serve req }
+ CALL = ActiveSupport::Ractors.shareable_lambda { |app, req| app.call req.env }
アプリケーション呼び出しロジックは保持されたままです。
routing/route_set.rb の URL ヘルパー生成ラムダがブロック形式に置き換えられました。
- PATH = ActiveSupport::Ractors.shareable_lambda(&->(options) { ActionDispatch::Http::URL.path_for(options) })
- UNKNOWN = ActiveSupport::Ractors.shareable_lambda(&->(options) { ActionDispatch::Http::URL.url_for(options) })
+ PATH = ActiveSupport::Ractors.shareable_lambda { |options| ActionDispatch::Http::URL.path_for(options) }
+ UNKNOWN = ActiveSupport::Ractors.shareable_lambda { |options| ActionDispatch::Http::URL.url_for(options) }
URL 生成のアルゴリズムは変わりません。
active_support/log_subscriber.rb のログレベル判定ラムダがブロックリテラルへ統一されました。
- debug: ActiveSupport::Ractors.shareable_lambda(&-> (logger) { !logger.debug? }),
- info: ActiveSupport::Ractors.shareable_lambda(&-> (logger) { !logger.info? }),
- error: ActiveSupport::Ractors.shareable_lambda(&-> (logger) { !logger.error? }),
+ debug: ActiveSupport::Ractors.shareable_lambda { |logger| !logger.debug? },
+ info: ActiveSupport::Ractors.shareable_lambda { |logger| !logger.info? },
+ error: ActiveSupport::Ractors.shareable_lambda { |logger| !logger.error? },
判定ロジックは同一で、記法が簡潔になっています。
設計判断
変更は API 互換性を保持したまま記述スタイルのみを変更するという方針に基づいています。shareable_lambda が生成するオブジェクトは同一で、引数の数や戻り値の型に差異はありません。そのため、既存の呼び出し側コードは影響を受けません。
ブロックリテラルへの統一は Ruby 標準の構文を利用することで、コード解析ツールや自動リファクタリングの対象として扱いやすくなります。可読性向上が唯一の目的であり、設計上のトレードオフはありません。
まとめ
今回の PR は ActionPack と ActiveSupport の複数箇所で ActiveSupport::Ractors.shareable_lambda の記述を &-> からブロックリテラルへ置き換え、コードの見た目をシンプルにしました。振る舞いは変わらず、既存の機能に対する影響はありません。可読性の向上により、開発者が意図をすぐに把握できるようになります。