我有一点问题:我无法在AR中编写sql-query。
所以,我有Project
和Task
个型号,Project has_many Tasks
。 Task
有aasm-field(即“status”;但无关紧要,我可以是简单的int或字符串字段)。
所以,我想在我的项目索引页面列表中列出所有(最后)项目,并且我希望每个项目都计算它是活动的,待定的和已解决的(例如)任务。
像这样,看看:
因此,我确定可以使用@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 :(得分:0)
我建议在项目模型中使用计数器缓存,以防止需要在索引页面的每个显示上重新计算所有任务 - 拥有active_count,pending_count和resolved_count,并在任务更改状态时更新它们。
如果您只想修改现有代码,请尝试:
project.tasks.count(:conditions => "status = 'active'")
您还可以在任务模型中添加一个范围,使您可以执行以下操作:
project.tasks.active.count
修改的
好的,所以我半睡半醒 - 从你的问题中得到了错误的印象:/
是的,您可以在一个查询中执行此操作 - 使用find_by_sql来获取项目以及任务的分组计数。您将能够在结果项目数组中访问组计数。
答案 1 :(得分:0)
您可以使用分组和计数进行查找。类似的东西:
status_counts = project.tasks.find(:all,
:group => 'status',
:select => 'status, count(*) as how_many')
这会返回一个Task
类似对象的列表,其中包含status
和how_many
属性,您可以使用这些属性来提供摘要。 E.g。
<%= status_counts.map { |sc| "#{sc.how_many} #{sc.status} }.to_sentence %>
答案 2 :(得分:0)
也许你可以在你的项目控制器中:
Project.all
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
。
答案 3 :(得分: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')