活动记录和sql存在问题
我有一个小问题:我不能在AR中编写sql查询 所以,我有活动记录和sql存在问题,sql,ruby-on-rails,activerecord,Sql,Ruby On Rails,Activerecord,我有一个小问题:我不能在AR中编写sql查询 所以,我有Project和Task模型,Project有很多任务任务有aasm字段(即“状态”;但这并不重要,我可以是简单的int或string字段) 因此,我希望在我的项目索引页面上列出所有(最后一个)项目,并且对于我想要的每个项目,它都是活动的、挂起的和已解决的(例如)任务 就像这样,看看: 第一个项目(1个活动项目,2个待定项目, 10(已解决) 第二个项目(4) 活动,2个待定,2个已解决) 所以,我当然可以用@projects=Proj
Project
和Task
模型,Project有很多任务<代码>任务
有aasm字段(即“状态”;但这并不重要,我可以是简单的int或string字段)
因此,我希望在我的项目索引页面上列出所有(最后一个)项目,并且对于我想要的每个项目,它都是活动的、挂起的和已解决的(例如)任务
就像这样,看看:
- 第一个项目(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。问题很简单:
如何?
我建议在项目模型中使用计数器缓存,以避免需要在索引页的每个显示上重新计算所有任务-具有活动计数、挂起计数和已解决计数,并在任务状态更改时更新它们
如果您只想修改现有代码,请尝试:
project.tasks.count(:conditions => "status = 'active'")
您还可以向任务模型添加一个范围,使您能够执行以下操作:
project.tasks.active.count
status_counts = project.tasks.find(:all,
:group => 'status',
:select => 'status, count(*) as how_many')
编辑
好吧,我半睡着了-从你的问题中得到了错误的印象:/
是的,您可以在一个查询中完成这项工作—使用find_by_sql获取您的项目以及任务的分组计数。您将能够访问生成的项目数组中的组计数。您可以通过分组和计数进行查找。比如:
project.tasks.active.count
status_counts = project.tasks.find(:all,
:group => 'status',
:select => 'status, count(*) as how_many')
这将返回一个类似于任务
的对象列表,这些对象具有状态
和多少属性,然后您可以使用这些属性给出摘要。例如
<%= status_counts.map { |sc| "#{sc.how_many} #{sc.status} }.to_sentence %>
也许您可以在项目控制器中:
获取所有项目: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)
第一个项目(活动)
这不是完美的解决方案,但很容易实现,并且只使用两个(大)查询。当然,每次都会重新创建一个散列,所以您可能希望查看数据库索引或缓存系统
另外,这也很有趣,比如任务.active
所以,正确的答案是:
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')
除了柜台,你还有别的想法吗?我不想使用它们,所以我会在最后一个案例中使用它们。谢谢我需要这样的东西,但我想做@projects=>>current_user.projects.find(:all,:joins=>:tasks,:select=>“projects.*,count(tasks.id)as active”,:group=>“status”)之类的事情,但我真的不能划分active/inactive/等等。我想得到这样的东西“projects.id、projects.title、活动计数、非活动计数、挂起计数“。我不完全相信你可以只做一次大规模的查询就得到所有项目和所有任务。如果这就是你想要的,那么马特先生建议的计数器缓存方法肯定是最好的。如果我只选择最近的任务,计数器缓存现在可以工作了(或者我应该每天通过cron重新加载计数器)。是的,我真的需要你描述的。无论如何谢谢你!可能有很多任务,所以我不想获取所有记录,只想获取其中的COUNT()。