如何按特定优先级对activerecord查询进行排序

问题描述 投票:0回答:3

我正在使用 Rails 3 和 postrges。

我想要按特定优先级排序。

类似:

Assignment.order(priority: ['best', 'good', 'bad'])

这将首先返回所有活动记录,其中包含“最佳”,然后是“好”,然后是“坏”

我似乎找不到这样的东西。我不需要数组,它必须是 activerecords。

ruby-on-rails ruby-on-rails-3 activerecord
3个回答
30
投票

命令可以是任何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])
从控制器传入排序。


10
投票

在较新版本的 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
  )
)

0
投票

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
© www.soinside.com 2019 - 2024. All rights reserved.