Ruby 3.1 がリリースされた!
今年も無事にクリスマスに Ruby がリリースされました!
Ruby 3.1 で追加される機能などは以下のスライドで紹介しているので気になる人は読んでみてください。
Ruby 3.1 へ移行するときの注意点
Ruby 3.1 で非互換になった機能があるのでいくつか紹介します。
これ以外にも細かい変更点はあるので詳しくは NEWS などを参照してください。
YAML.load
が非互換になる
Ruby 3.1 では YAML の実装である Psych
のバージョンが 4.0.0
にメジャーアップデートされます。
この影響により YAML.load
など一部の機能が非互換になります。
例えば YAML.load
が YAML.safe_load
に置き換わったので次のようにエイリアスを使用している YAML ファイルは YAML.load
では読み込めなくなります。
require "yaml" data = <<~EOS default: &default aaa: aaa development: <<: *default EOS # Ruby 3.0 => OK 読み込める # Ruby 3.1 => NG 読み込めない pp YAML.load(data)
これを回避する方法として YAML.unsafe_load
を使用する方法があります。
# OK # .unsafe_load を使用すると Ruby 3.1 でも読み込めるようになる pp YAML.unsafe_load(data)
読み込んでいる YAML ファイルによっては動かなくなる可能性があるので注意しましょう。
他にも非互換になった箇所があるので詳しくは以下の記事を参照してください。
- Ruby の YAML.load が非互換になる(かもしれない) - Secret Garden(Instrumental)
- Ruby の Psych.safe_load(YAML.safe_load)の引数が Psych v4.0.0 から非互換になる - Secret Garden(Instrumental)
Class#descendants
が Ruby 3.1 には入らなかった
Ruby 3.1 には Class#descendants
という新しいメソッドが入る予定だったんですが直前で Revert されました。
そもそも入ってないので基本的に既存のコードには影響はないのですが Rails 7.0.0 がこの Class#descendants
に依存している関係で Rails 7.0.0 と Ruby 3.1 の組み合わせだと動かない可能性があるので注意する必要があります。
この問題は Rails 7.0.1 (仮) で対応される予定です。
Module#prepend
の挙動が調整
『既に継承リストに存在しているモジュールを prepend
した』ときの挙動が調整されました。
これによって以下のように Ruby 2.7 ~ 3.1 間で全ての挙動が異なるのでちょっとだけ気にしておく必要があります。
module M1; end module M2; end class A; include M2; end M2.prepend M1 A.prepend M1 p A.ancestors # 2.7 => [M1, A, M2, Object, Kernel, BasicObject] # 3.0 => [A, M1, M2, Object, Kernel, BasicObject] # 3.1 => [M1, A, M1, M2, Object, Kernel, BasicObject]
refine
内での include / prepend
が非推奨になった
refine
内での include / prepend
が非推奨になりました。
-W
を付けて Ruby を実行すると警告が出るようになります。
using Module.new { module Twice def twice self + self end end refine String do # warning: Refinement#include is deprecated and will be removed in Ruby 3.2 include Twice end refine Integer do # warning: Refinement#include is deprecated and will be removed in Ruby 3.2 include Twice end } pp "homu".twice pp 42.twice
これの代替として import_methods
という機能が新しく追加されたので今後は import_methods
を使っていく必要があります。
# 使い方は一緒 using Module.new { module Twice def twice self + self end end refine String do # no warning import_methods Twice end refine Integer do # no warning import_methods Twice end } pp "homu".twice pp 42.twice
foo[0], bar.baz = a, b
の評価順が変更
多重代入を行った際の評価順が変わりました。
以下のようなコードは
foo[0], bar.baz = a, b
Ruby 3.0 では以下の評価順です。
a
が評価されるb
が評価されるfoo
が評価されるfoo
の[]=
が評価される(foo[0]=
)bar
が評価されるbar
のbaz=
が評価される(bar.baz=
)
Ruby 3.1 では以下のような評価順になります。
foo
が評価されるbar
が評価されるa
が評価されるb
が評価されるfoo
の[]=
が評価される(foo[0]=
)bar
のbaz=
が評価される(bar.baz=
)