无法通过虚拟属性对活动管理员中的记录进行排序

时间:2019-03-21 11:35:49

标签: mysql ruby ruby-on-rails-4 activerecord activeadmin

无法按虚拟属性对活动管理员中的记录进行排序。

我有一个模型Competition

竞争有2个列,分别为starts_atends_at

比赛可以在其starts_atends_at日期中处于任何一种状态。

    如果starts_at < Time.now && ends_at > Time.now
  • 打开 如果Time.now > ends_at
  • 已关闭 如果starts_at > Time.now
  • 未打开

我想按此顺序对状态进行排序(也可以相反)

  1. 打开在顶部
  2. 打开后
  3. 关闭
  4. 最后
  5. 未打开

文件/admin/competition.rb

方法:index

虚拟属性:Status

column "Status" , sortable: true do |competition|
    competition.status
end

文件app/model/copetition.rb

获取状态的方法

def status
    return 'Unknown' unless (starts_at && ends_at)
    return 'Not Opened' if Time.now < starts_at
    return 'Open' if (Time.now > starts_at && Time.now < ends_at)
    return 'Closed' if Time.now > ends_at
end

我找不到应用这种排序的方法。

其他信息

'rails', '4.2.6'

ruby '2.2.4'

'activeadmin', '1.0.0.pre4'

2 个答案:

答案 0 :(得分:0)

将原始SQL与ActiveRecord::QueryMethods#order一起使用:

.order("
  IF(starts_at < NOW() AND ends_at > NOW(), 1,
    IF (NOW() > ends_at, 0, -1)) DESC
")

答案 1 :(得分:0)

由于排序是在数据库级别执行的,因此无法按activeadmin中的虚拟属性进行排序。

但是,您可以使用相同的逻辑来计算SQL中所需的字段并改为使用它。

您必须修改activeadmin的默认集合SQL查询并添加您的计算字段,以便能够将其用于排序。

# /admin/competition.rb

ActiveAdmin.register Competition do
  # modify the collection SQL query to add the needed field
  controller do
    def scoped_collection
      super.select(
        "competitions.*,
         CASE
         WHEN starts_at < NOW() THEN 3
         WHEN ends_at > NOW() THEN 2
         ELSE 1
         END AS status_from_sql"
      )
    end
  end

  # using the added field for sorting
  column "Status" , sortable: "status_from_sql" do |competition|
    competition.status
  end    
end