Ruby
Rails

Rails 6 以降は order/pluck の引数に SQL 文字列を渡すことはできない (容易に対策可能)

More than 1 year has passed since last update.


問題点

あるプロジェクトの Rails のバージョンを 5.1 から 5.2 に上げると次のコードで警告が発生するようになった。

Item.order('COALESCE(order_no, 0)')


DEPRECATION WARNING: Dangerous query method (method whose arguments are used as raw SQL) called with non-attribute argument(s): "COALESCE(order_no, 0)". Non-attribute arguments will be disallowed in Rails 6.0. 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().


Rails 5.2 では警告が表示されるだが、Rails 6 ではエラーになる (例外が発生する) 模様。


対策

前述の警告の通り、SQL 文字列を Arel.sql() でラップするとよい。

Item.order(Arel.sql('COALESCE(order_no, 0)'))


非推奨になった理由

SQL インジェクションを防ぐため。

# 何かしらのコントローラ

Item.order(params[:order]) # 外部から悪意のあるパラメータが渡される可能性がある。

詳しくは次の issue を参照のこと。

rails/rails » Issue #27947 » Disallow raw SQL in dangerous AR methods