問題点
あるプロジェクトの 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