エラー内容
エラー内容は以下。
ActiveRecord: :UnknownAttributeReference: Dangerous query method (method whose arguments are used as raw SQL) called with non-attribute argument(s): "field(id, ?)".This method should not be called with user-provided values, such as request parameters or model attributes. Known-safe values can be passed by wrapping them in Arel.sql().
要は、「field(id, ?)はSQLインジェクションの危険があるから、危険じゃないことを確認できてるならArel.sql()で囲め」とのこと。
エラー出た部分のコードは以下の様な感じ。
User.where(id: ids).order(['field(id, ?)', ids])
whereしてきたid一覧と同じ順番でレコードを取得したいときにやるやつですね(MySQL限定)。
以前のRailsでも警告はされていた様ですがRails7からはエラーとして上がってくる様になったみたいです。
解決法
言われた通りArelで囲んでも解決しますが、この様なケースの時に使えるメソッドがRails7から追加されています。
https://techracho.bpsinc.jp/hachi8833/2021_10_28/113117
このin_order_of
を使って書き換えてみることにします。
user = User.in_order_of(:id, [3, 5, 2, 4, 1])
# => User Load (0.6ms) SELECT `users`.* FROM `users` WHERE `users`.`id` IN (3, 5, 2, 4, 1) ORDER BY FIELD(`users`.`id`, 1, 4, 2, 5, 3) DESC
user.pluck(:id)
# => [3, 5, 2, 4, 1]
正しい順番で取れてきている様です。field句を使っているみたいですがMySQL以外の時はどうなるのか気になるところですね。また、配列逆順にしてDESCで取ってくるのはなんでなのか気になりますね。普通に同順にしてASCでもいいのではないかという気はします。
Rails 7にアップグレードする際は事前に上記の警告を潰しておいた方がよさそうです。