【定期配信】最新のRuby & Railsへのバージョンアップ時の注意点 (~ 2021-11-11)
Ruby と Rails を安定して使い続けるために 最新の Ruby と Rails に対して行われた変更がバージョンアップするときに問題になるかどうか という観点で情報をまとめています。
情報が多いので時間がない人は Rubyの仕様変更の一覧 と Railsの仕様変更の一覧 を見てください。
Ruby の最新情報は nagachikaさん (@nagachika) / Twitter が ruby trunk changes で公開してくださっています。
Rails の最新情報は Pull requests · rails/rails でマージされた PR を確認できるのと、y-yagiさん (@y_yagi) / Twitter が なるようになるブログ で公開してくださっています。
これらは大変有益な情報です。本当にありがたいことです。
Google広告
Ruby
Rubyの仕様変更の一覧
ruby trunk (ruby 3.1)
- rb_gc_force_recycle()
- net/http
- HEAD リクエスト
以下、変更点の詳細です。
ruby trunk
ruby-trunk-changes 2021-11-08 - ruby trunk changes
OK
ruby-trunk-changes 2021-11-09 - ruby trunk changes
[Feature #18290] Deprecate rb_gc_force_recycle and remove invalidate_… · ruby/ruby@3094064
【仕様変更】
rb_gc_force_recycle()
が deprecated になりました。が、まぁ、使っている人は少ないでしょうね…
ruby-trunk-changes 2021-11-10 - ruby trunk changes
OK
ruby-trunk-changes 2021-11-11 - ruby trunk changes
OK: revert
2ヶ月前のruby trunkの仕様変更でString処理全般でSEGVが発生することがあったのですが、それを元に戻しています。
[ruby/net-http] Send Accept-Encoding header on HEAD method · ruby/ruby@52ab9bb
【仕様変更】
標準添付ライブラリ net/http で HEAD リクエストに Accept-Encoding を設定するように修正。
Accept-Encodingによってレスポンスがかわることもあるかもしれません。HEAD リクエストを送っている場合は要チェックです。
ruby 3.0
変更なし。
ruby 2.7
変更なし。
Google広告
Rails
Railsの仕様変更の一覧
rails 7.0
- ActiveRecord
- has_many に proc と through を指定している場合
以下、変更点の詳細です。
Pull requests
Pull requests · rails/rails 2021-11-08
日本語の解説: rails commit log流し読み(2021/11/08) - なるようになるブログ
OK: rails newに関する修正
Fix preloading for hmt relations with conditions by apauly · Pull Request #43132 · rails/rails
【仕様変更】
バグ修正なんだけど、一応、仕様変更とします。
不具合の再現コードはこちら: ActiveRecord - Preloading a hmt relation ignores class_name option · Issue #43175 · rails/rails
以下の special_categories
ように has_many
に proc を指定している場合は要チェック。
has_many :category_posts
has_many :categories, through: :category_posts
has_many :special_categories, -> { where(some_flag: true) }, through: :category_posts, source: :category, class_name: "SpecialCategory"
なお、この修正は6.1にもバックポートされています。
6.0系と同じ挙動になり、6.0系から6.1系へのバージョンアップがより楽になりますね。
Pull requests · rails/rails 2021-11-09
日本語の解説: rails commit log流し読み(2021/11/09) - なるようになるブログ
OK: doc
Document
tag.attributes
helper [ci-skip] by seanpdoyle · Pull Request #43614 · rails/rails
OK: doc
Pull requests · rails/rails 2021-11-10
日本語の解説: rails commit log流し読み(2021/11/10) - なるようになるブログ
OK: refactor
この PR で知ったのですが Rails standardized error reporting interface · Issue #43472 · rails/rails にて、標準的なエラーレポートの仕組みが検討されています。オプションを指定するだけでエラーレポートの送信先を Sentry や Airbrake に切り替えることができるようになりそうです。これはイイです!
Pull requests · rails/rails 2021-11-11
日本語の解説: rails commit log流し読み(2021/11/11) - なるようになるブログ
OK: doc
以下のようにMySQLだとindexのデータ長を指定できるようです。
add_index(:accounts, [:name, :surname], name: 'by_name_surname', length: {name: 10, surname: 15})
OK: doc
Google広告
今回のおまけ
うれしいですね!
リリースノートに書かれている言語仕様の変更のうち、問題となりそうなものが1つありました (とはいえ、現状だと困るものを修正しただけなので問題となるのはコーナーケースだと思われます)。
Multiple assignment evaluation order has been changed slightly. [Bug #4443]]
foo[0], bar[0] = baz, qux was evaluated in order baz, qux, foo, and then bar in Ruby 3.0. In Ruby 3.1, it is evaluated in order foo, bar, baz, and then qux.
↑のように多重代入の評価順が変わりました。
Bug #4443: odd evaluation order in a multiple assignment - Ruby master - Ruby Issue Tracking System に再現コードがあります。
def foo
p :foo
[]
end
def bar
p :bar
end
x, foo[0] = bar, 0
↑の出力は、ruby 2.6.6 では :bar, :foo の順。
ruby 3.1.0 preview 1では :foo, :bar の順です。
左から順に評価されます。
これによって、以下のようなコードでスワップできるようになるというメリットがあります。obj.foo は配列を返すメソッドとかです。
obj, obj.foo = obj.foo, obj
逆に スワップしないことを期待している場合 には問題になります。まったくよい例が思いつきませんが、以下のように、多重代入の左辺と右辺で同じレシーバーのメソッド呼び出しをしていて、なおかつ値がスワップしてほしくない場合です (スワップしてほしくないケースってあるのかな?)。
model.attr1, model.attr2 = model.attr2, model.attr1
あくまでも問題となる可能性があるだけです。というのも、期待とは異なりスワップしないのですから、このコードはまずいと気がつき、その時点で修正しているでしょう。
ということで、多重代入の評価順は Ruby のバージョンによって変わるため、多重代入の評価順に依存しないようなコードを書くようにしましょう。
とはいえ、多重代入を使うなってことではないため、しれっと古いRubyでは動かないコードを書いてしまいそうだけど、そのようなケースってあるのかな…?