[Rails] Ruby 4.1の stabby lambda 構文に対応したProc#source_location処理の改善
背景
Ruby 4.1では、Proc#source_locationの挙動が変更され、stabby lambda(->)構文で定義されたProcのソースコード位置情報がより正確になりました。具体的には、start_columnの値がlambda定義の先頭(->の位置)を指すようになったため、既存のソースコード抽出ロジックではstabby lambda記法がそのまま残ってしまう問題が発生しました。
この変更は、RailsのテストアサーションでProcのソースコードを文字列化する際に影響を与えるため、Ruby 4.1との互換性を保つための対応が必要となりました。
技術的な変更内容
修正箇所
Active Supportの_callable_to_source_stringメソッドにおいて、ソースコードから stabby lambda 記法を除去する処理が追加されました。
変更後:
def _callable_to_source_string(callable)
# ... 既存の処理 ...
lines[0] = lines[0].byteslice(location[1]...)
source = lines.join.strip
# Strip stabby lambda from Ruby 4.1+
source = source.sub(/^->\s*/, "")
# We ignore procs defined with do/end as they are likely multi-line anyway.
if source.start_with?("{")
source.delete_suffix!("}")
end
# ...
end
処理の詳細
source.sub(/^->\s*/, "") により、以下の変換が行われます:
-
-> { code }→{ code } -
-> { code }→{ code }(スペースも含めて除去)
この処理により、Ruby 4.1以降でも従来通り、波括弧で囲まれたlambda本体のみを抽出できるようになります。
影響範囲
この変更は主にテストアサーションの内部処理に影響します。具体的には、assert_changesやassert_differenceなどのアサーションメソッドで、Procのソースコードをエラーメッセージに含める際の表示が改善されます。
Ruby 3.x系では従来通りの動作が維持され、Ruby 4.1以降では新しいsource_locationの挙動に適切に対応します。後方互換性を保ちながら、将来のRubyバージョンへの対応を実現した変更です。
まとめ
このバックポートにより、Rails 8.0安定版でもRuby 4.1のProc#source_locationの変更に対応できるようになりました。stabby lambda記法を正規表現で除去するシンプルな実装により、最小限の変更でRuby 4.1互換性を確保しています。