[Rails] Ruby 4.1のstabby lambda構文変更に対応したProc#source_location処理の修正
背景
Ruby 4.1では、stabby lambda(->)の構文においてProc#source_locationのstart_columnの振る舞いが変更されました。これまでlambdaの本体({)から始まっていた位置情報が、->記号から始まるようになったため、Active Supportのテストアサーション機能で使用している_callable_to_source_stringメソッドが正しく動作しなくなる問題が発生しました。
この変更は、Ruby 4.1以降でRailsのテストを実行した際に、assert_differenceなどのアサーションメソッドでlambdaを使用したコードが期待通り動作しない原因となっていました。
技術的詳細
変更箇所
# Strip stabby lambda from Ruby 4.1+
source = source.sub(/^->\s*/, "")
_callable_to_source_stringメソッドに、stabby lambda記号を取り除く処理を追加しています。この処理は、ソースコードの先頭から->とそれに続く空白文字を削除します。
Ruby 4.1での動作変化
Ruby 4.0以前:
```ruby
lambda = -> { 1 + 1 }
lambda.source_location
=> ["file.rb", 1, 3] # '{' の位置から開始
**Ruby 4.1以降:**
```ruby
lambda = -> { 1 + 1 }
lambda.source_location
# => ["file.rb", 1, 0] # '->' の位置から開始
この変更により、byteslice(location[1]...)で切り出されたソース文字列が"-> { 1 + 1 }"となり、start_with?("{")のチェックが失敗するようになりました。
修正の影響
今回の修正により、Ruby 4.1以降でも以下のようなテストコードが正常に動作します:
assert_difference -> { User.count }, 1 do
User.create!(name: "Alice")
end
この修正は後方互換性を保っており、Ruby 4.0以前でも問題なく動作します。Ruby 4.0以前ではsource変数に"->"が含まれていないため、subメソッドは何も置換せずに元の文字列を返します。
影響範囲
この変更は8.1系の安定版ブランチへのバックポートであり、Ruby 4.1以降を使用する環境でRails 8.1を利用する場合に必要な修正です。Active Supportのテストアサーション機能を使用しているすべてのテストコードが対象となります。