如何根据子类的属性对父类进行排序?

时间:2011-04-04 21:12:38

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

我觉得我有一个简单的要求:我想根据子类的属性对父类进行排序。

class owner
  has_many :tasks
end

class task
  belongs_to :owner
end

现在我想根据任务的截止日期对所有者进行排序,以便具有“最接近”截止日期的任务的所有者是第一个,等等

我可以使用数组排序在Ruby中执行此操作,但我的记录集非常庞大,我需要使用AR / DBMS执行此操作..

更新
正如我在思考这个问题时,解决方案的一部分发生在我身上,虽然我不知道如何在AR中实现。

要根据所有者的任务对所有者进行排序,只有一个任务(每个所有者)是相关的,即具有最接近截止日期的任务。

我如何使用AR向我提取所有所有者,按其最接近的截止日期排序?

更新2:

Task.order("due_date DESC").maximum("due_date", :group => 'owner')

实际上会给我所有者对象,按照正确的顺序排序,作为有序哈希的一部分([owner] =>“due_date”)。万岁!现在唯一的问题是,如何告诉AR使用所有者对象eager_load所有相关任务。因为此时它每次调用时都会触发查询

owner.tasks.each do |t|

在我看来。

任何帮助表示赞赏,我对此(简单?)问题感到困惑,
欧文

2 个答案:

答案 0 :(得分:2)

好的,最后我自己想出来了。

Owner.includes(:tasks).joins(:tasks).order("tasks.due_date").group(:id)

将根据任务中最接近的截止日期对所有者进行排序,并急切加载所有任务,从而产生单个查询。

更新:添加生成的SQL以响应下面的Mladen评论。

SELECT `owners`.* FROM `owners` 
INNER JOIN `tasks` ON `tasks`.`owner_id` = `owner`.`id` 
GROUP BY owner.id ORDER BY tasks.due_date DESC

干杯。

答案 1 :(得分:0)

只能通过纯查询找到这个:

Owner.find_by_sql('SELECT `owners`.*,
                           (SELECT `tasks`.`due_date`
                            FROM `tasks`
                            WHERE `owners`.`id` = `tasks`.`owner_id`
                            ORDER BY `tasks`.`due_date` DESC LIMIT 1) AS `last_due_date`
                   FROM `owners`
                   GROUP BY `owners`.`id`
                   ORDER BY `last_due_date` DESC;')

如果需要访问last_due_date,请添加到Owner型号:

def last_due_date
  if attributes['last_due_date']
    attributes['last_due_date']
  else
    tasks.order(due_date: :desc).limit(1).first.due_date if tasks.length > 0
  end
end