0
Help us understand the problem. What are the problem?

Rails 7.0.2にアップグレード後、SQLインジェクションの危険性のあるクエリがエラーになった

エラー内容

エラー内容は以下。

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にアップグレードする際は事前に上記の警告を潰しておいた方がよさそうです。

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
0
Help us understand the problem. What are the problem?