我正在使用 Rails 3 和 postrges。
我想要按特定优先级排序。
类似:
Assignment.order(priority: ['best', 'good', 'bad'])
这将首先返回所有活动记录,其中包含“最佳”,然后是“好”,然后是“坏”
我似乎找不到这样的东西。我不需要数组,它必须是 activerecords。
命令可以是任何SQL代码。您可以使用
CASE
语句将您的值映射到自然按正确顺序排序的值。
Assignment.order("
CASE
WHEN priority = 'best' THEN '1'
WHEN priority = 'good' THEN '2'
WHEN priority = 'bad' THEN '3'
END")
更好的是,您可以将此逻辑移至模型中,以便更轻松地从控制器调用:
class Assignment < ActiveRecord::Base
...
def self.priority_order
order("
CASE
WHEN priority = 'best' THEN '1'
WHEN priority = 'good' THEN '2'
WHEN priority = 'bad' THEN '3'
END")
end
end
然后您只需拨打
Assignment.priority_order
即可获取已排序的记录。
如果此列在视图中可排序,请向方向方法添加一个参数:
def self.priority_order(direction = "ASC")
# Prevent injection by making sure the direction is either ASC or DESC
direction = "ASC" unless direction.upcase.match(/\ADESC\Z/)
order("
CASE
WHEN priority = 'best' THEN '1'
WHEN priority = 'good' THEN '2'
WHEN priority = 'bad' THEN '3'
END #{direction}")
end
然后,您可以调用
Assignment.priority_order(params[:direction])
从控制器传入排序。
在较新版本的 Rails 中,如果将原始 SQL 传递给
ActiveRecord::UnknownAttributeReference (Query method called with non-attribute argument(s)
,您将收到 .order()
错误。
您需要用
Arel.sql()
包装 SQL 查询。您还可以使用 ruby 的 Here Doucment 语法来编写多行 SQL 语句,并使用 squish 使其在控制台中更具可读性。
所以整个事情就变成了:
Assignment.order(
Arel.sql(<<-SQL.squish
CASE
WHEN priority = 'best' THEN '1'
WHEN priority = 'good' THEN '2'
WHEN priority = 'bad' THEN '3'
END
SQL
)
)
Rails 7 中引入了 ActiveRecord 查询方法
in_order_of
。
参见 https://edgeapi.rubyonrails.org/classes/ActiveRecord/QueryMethods.html#method-i-in_order_of
允许通过一组特定值指定顺序。
User.in_order_of(:id, [1, 5, 3])
# SELECT "users".* FROM "users"
# WHERE "users"."id" IN (1, 5, 3)
# ORDER BY CASE
# WHEN "users"."id" = 1 THEN 1
# WHEN "users"."id" = 5 THEN 2
# WHEN "users"."id" = 3 THEN 3
# END ASC