Starting Rails 6.0, @hieu-pham's solution will throw this deprecation warning: "Dangerous query method (method whose arguments are used as raw SQL) called with non-attribute argument(s) [..] Non-attribute arguments will be disallowed in Rails 6.1. 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()."
So, building up on both his answer and @fellow-stranger's, I'd suggest this:
class YourModel < ActiveRecord::Base
ROLE_ORDERS = [2, 0, 1]
scope :order_by_role, -> { order(Arel.sql(ROLE_ORDERS.map{ |role| "role=#{role} DESC" }.join(', '))) }
end
Then this is used in your code just as in @hieu-pham's solution...
YourModel.order_by_role
... which generates this query:
SELECT * from your_models
ORDER BY role = 2 DESC, role = 0 DESC, role = 1 DESC