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

时间:2014-05-12 23:35:31

标签: ruby-on-rails ruby-on-rails-3 activerecord

我正在使用rails 3和postrges。

我想按特定优先顺序订购。

类似的东西:

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

这将首先以'best',然后'good',然后'bad'返回所有activerecords

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

2 个答案:

答案 0 :(得分:19)

订单可以是任何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])从控制器传递排序。

答案 1 :(得分:2)

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