ActiveRecord::Relation with raw SQL argument returns a warning/exception raising.
Fix up with Arel.sql()
2 min readMar 29, 2019
In Ruby on Rails > 5.2,
If you still want to use #order
or #pluck
on our ActiveRecord::Relation using SQL syntax like this[1]. You may need to use Arel.sql()
to avoid unsafe_raw SQL warning like following[2]:
DEPRECATION WARNING: Dangerous query method (method whose arguments are used as raw SQL) called with non-attribute argument(s): "SOMETHING". 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().
And in Ruby on Rails >= 6, it will become to a exception raising:
ActiveRecord::UnknownAttributeReference (Query method called with non-attribute argument(s): "SOMETHING")
This is what you can do:
# Make sure it's a known-safe values.user_ids = [3, 2, 1]# Before
users = User.where(id: user_ids).order("FIELD(id, 2, 3, 1)")# With warning.
# After
users = User.where(id: user_ids).order(Arel.sql("FIELD(id, 2, 3, 1)"))# No warning
NOTICE:
Not every raw SQL argument will bring on this warning:
User.where(id: user_ids).order('users.id desc')
User.where(id: user_ids).order('id desc')
User.where(id: user_ids).order('id')
User.where(id: user_ids).order('users.id')
User.where(id: user_ids).pluck('users.id')
User.where(id: user_ids).pluck('id')# All of these with correct column format will be allowed
Check all column format white list here[3].
Reference:
[1] Ordering ActiveRecord::Relation with SQL argument
[2] Rails’ PR: Disallow raw SQL in dangerous AR methods #27947