2010-10-06 81 views
0

我有一个小问题:我无法在AR内部编写sql-query。活动记录和sql的问题

所以,我有ProjectTask型号,Project has_many TasksTask有aasm字段(即“状态”;但它并不重要,我可以是简单的int或字符串字段)。

因此,我希望在我的项目索引页面列表中列出所有(最后一个)项目,并且为每个我希望计划的项目计算它的活动,挂起和解决(例如)任务。

与此类似,只是看:

  • 第一个项目(1个活动,2待定, 10解决)
  • 二项目(4 活跃,2待定,2解决)

所以,当然我可以用@projects = Project.all做到这一点,然后看:

- @projects.each do |project| 
    = project.title 
    = project.tasks(:conditions => {:status => "active"}).count #sure it should be in model, just for example 
    = project.tasks(:conditions => {:status => "pending"}).count 
    # ... 
- end 

这很好,但是使1 + N * 3(对于3个任务状态)查询,我想要1.问题很简单:how?

回答

0

所以,正确的答案是:

Projects.all(:joins => :tasks, 
      :select => 'projects.*, 
         sum(tasks.status="pending") as pending_count, 
         sum(tasks.status = "accepted") as accepted_count, 
         sum(tasks.status = "rejected") as rejected_count', 
      :group => 'projects.id') 
0

我建议在您的项目模型中使用计数器缓存,以防止需要重新计算每个索引页面上的所有任务 - 具有active_count,pending_count和resolved_count,并在任务更改状态时进行更新。

如果你只是想修改现有的代码,请尝试:

project.tasks.count(:conditions => "status = 'active'") 

你也可以一个范围添加到您的任务模式,将让你做这样的事情:

project.tasks.active.count 

编辑

好吧所以我半睡半醒 - 从你的问题得到错误的印象:/

是的,你可以在一个查询中完成它 - 使用find_by_sql来获取你的项目以及任务的分组计数。您将能够访问所产生的项目数组中的组计数。

+0

你有除了counter_cache什么想法?我不想使用它们,所以我会在最后一种情况下使用它们。谢谢! – 2010-10-06 09:00:57

0

您可以通过分组和计数来查找。喜欢的东西:

status_counts = project.tasks.find(:all, 
            :group => 'status', 
            :select => 'status, count(*) as how_many') 

这将返回Task般对象的列表与statushow_many属性,你可以再使用,让您的摘要。例如。

<%= status_counts.map { |sc| "#{sc.how_many} #{sc.status} }.to_sentence %> 
+0

我需要像这样的东西,但我想要做一些像@projects = >> current_user.projects.find(:all,:joins =>:tasks,:select =>“projects。*,count(tasks.id )as active“,:group =>”status“) – 2010-10-06 09:37:57

+0

但我真的不能划分active/inactive/etc。 – 2010-10-06 09:39:19

+0

我想获得像“projects.id,projects.title,active_count,inactive_count,pending_count”的内容。 – 2010-10-06 09:40:16

0

也许你可以在你的项目负责人:

  1. 获取所有的项目:Project.all
  2. 获取所有的任务:Task.all

然后,创建的东西散像

@statuses = Hash.new 
@tasks.each do |t| 
    @statuses[:t.project_id][:t.status] += 1 
end 

,然后用它在你的观点:

First project (<%= @statuses[:@project.object_id][:active] %> active) 

这不是知府解决方案,但它很容易实现,只使用两个(大)查询。当然,每次都会重新创建一个散列,因此您可能需要查看数据库索引或缓存系统。

另外,named scopes会很有趣,像Task.active

+0

可以有很多任务,所以我不想获取所有记录,只有COUNT()。 – 2010-10-06 09:41:23