背景
ruby on railsで開発しているのですが、rubyのバージョンを上げようと思ったら躓いてしまいました。日本語だとあまり情報がなかったので記事にしてみました。
railsとrubyのバージョンは下記の通り。
rails: 6.1.7.7
ruby: 3.0.6 -> 3.2.3
そもそもスコープってなに?というかたは、こちらのリンクとかが参考になるかもしれません。
私が開発しているアプリでは、モデルの中でよく使う条件式をわかりやすい名前のスコープとして定義したりしてます。
何が起きたのか?
例えば下記のようなスコープがあったとします。
(実際はキーワード引数を使う必要はないと思いますが、あくまで例なので悪しからず)
User < ApplicationRecord
scope :younger_than,
lambda { |age:|
where(age: ...age)
}
end
使うときは、こんな感じでクラスメソッドのように使えます。
User.younger_than(age: 10)
> SELECT `users`.* FROM `users` WHERE `users`.`age` < 10 # こんなSQLが発行される
> [#<User id: 1, age: 5, ...>,
> #<User id: 3, age: 9, ...>] # ageが10未満のレコードを含むActiveRecord::Relationが返ってくる
railsのスコープは上記のようにキーワード引数が使えるのですが、rubyのバージョンを3.2にあげたところ下記のようなエラーが出るようになりました。
User.younger_than(age: 10)
> wrong number of arguments (given 1, expected 0; required keywords:age) (ArgumentError)
どうやらキーワード引数ではなく、ハッシュが位置引数として渡ってしまっているようです。
原因と対策
色々調べていると、railsのgithubで同様の問題をissueであげている人がいました。
issueの中を読んでみると、ruby 3.2からキーワード引数と扱い方が変わったらしく、それが影響してスコープでキーワード引数が使えなくなるとのこと。
しかも、残念ながらrails 6.1はセキュリティ対応のみ更新していく状態なので、今回のようなバグ対応はしないと、メンテナーから回答されていました。
一応対応したrails:6-1-stable
というブランチがあり、railsがリリースされるたびにこちらのブランチも更新されているようですが、リリースされているわけではないです。
というわけで対策は下記のどれかとなります。
- スコープのキーワード引数を位置引数の変える
- スコープをクラスメソッドにする
- ruby 3.1のままにする
- rails7にあげる
rails7に早くあげたいところではありますが、大仕事なのは目に見えているので、一旦スコープのキーワード引数を位置引数に変えて、計画的にrails7へあげていくことにしました。