2012-08-15 25 views
4

我有用户配置的列表,它可能(或可能不会)有一个或多个部件:如何在Rails COUNT列添加到工作查询与组()3.1

class UserProfile < ActiveRecord::Base 
    has_many :widgets 
end 

@all_profiles = UserProfile.joins(:widgets).group('user_profiles.id').order("name ASC") 

在索引视图,而不是在每个视图行中执行新的查询以获得小部件的数量为@all_profile.each,有没有办法给原始数据添加一个计数列,以显示每个分组行中有多少个小部件? (例如,如果存在N个@all_profiles,避免再次查询数据库N次?

(这非常重要,不仅避免N个额外的查询,还允许我们在count列上添加SORT选项,所以我们可以排序客户提供最部件)

回答

11

您可以通过ActiveRecord::QueryMethods#select

@all_profiles = UserProfile.joins(:widgets).select('user_profiles.*, COUNT(*) AS widget_count').group('user_profiles.id').order('name ASC') 

现在添加一个COUNT列,每个返回的对象将包含一个widget_count属性,你可以访问就像任何其他的模型属性:

@all_profiles.each do |profile| 
    puts profile.widget_count 
end 
+0

非常感谢你这么详细的答复!完美工作。 (我以前曾尝试将.select放在错误的位置) – jpwynn 2012-08-15 17:32:38

+0

虽然它在SQLITE3上正常工作,Postgres(Heroku)抛出一个错误:(PG :: Error:错误:列“widgets.id”必须出现在GROUP BY子句或在集合函数中使用)。用count(widgets.id)替换count(*),仍然可以在SQLITE上工作,但仍然会在Postgres上抛出相同的错误。我曾经想过使用rails activerecord抽象可以防止那些特定于dbase的问题。 – jpwynn 2012-08-15 17:48:10

+0

FWIW我们在heroku上使用postgres 9.1(新的基本计划) – jpwynn 2012-08-15 18:16:38

0

可以使用计数方法,具有:组参数:count

这应该是这个样子:

UserProfile.joins(:widgets).order(:name).count(:id, :group => 'user_profiles.id') 
+1

这只是返回一个哈希映射'UserProfile' ID到特定'UserProfile'的小部件计数。 OP要求将计数包括在原始查询中,这样除了计数之外,所有'UserProfile'属性都会返回。 – Brandan 2012-08-15 21:02:56