2012-07-07 59 views
2

用户可以提交资源并发表评论。按关联记录的数量排序记录

我想通过选择已提交资源和评论的用户来显示最活跃的用户,并将提交了最多资源和评论的用户的结果排序为最低。

**Resource** 
has_many :users, :through => :kits 
has_many :kits 
belongs_to :submitter, class_name: "User" 

**User** 
has_many :resources, :through => :kits 
has_many :kits 
has_many :submitted_resources, class_name: "Resource", foreign_key: "submitter_id" 

**Kits** 
belongs_to :resource 
belongs_to :user 

**Comments** 
belongs_to :user 

我是新来的这种sql在Rails中。我怎样才能得到这个记录集?

回答

2

首先,你需要将评论协会添加到用户模式:

has_many :comments 

这样,简单的办法是这样做:

User.all.sort do |a,b| 
    (a.submitted_resources.count + a.comments.count) <=> (b.submitted_resources.count + b.comments.count) 
end 

这会变得非常慢,所以如果你想做得更好,你会想添加计数器缓存。在迁移:

def up 
    add_column :users, :submitted_resources_count, :integer 
    add_column :users, :comments_count, :integer 

    User.reset_column_information 

    User.find_each do |u| 
    u.update_attributes! \ 
     :submitted_resources_count => u.submitted_resources.count, 
     :comments_count => u.comments.count 
    end 
end 

def down 
    add_column :users, :submitted_resources_count 
    add_column :users, :comments_count 
end 

一旦运行这个迁移,你可以改变原来的查询:

User.select('*, (submitted_resources_count + comments_count) AS activity_level').order('activity_level DESC') 

这将非常有效地恢复所有用户以正确的顺序,并作为奖励每个用户将有一个名为activity_level的只读属性,它将提供确切提交的资源+评论数。

+0

谢谢Tanzeeb,我有一个问题。 1. def-method中是否应该有remove_column:users,:submitted_resources_count? 2.我得知我运行这个迁移,但是User.find_each做的方法是| u |将仅在此次迁移时运行。那么,我需要将它放在一个范围内还是放在应用程序的其他位置,以便在我需要找到最活跃的用户时运行? – chell 2012-07-16 15:03:17

+0

伟大的问题。 1)是的。 down方法应该撤消,因为up会创建两列,down应该删除它们。 2)迁移中的更新设置了初始计数,但不需要再次调用。 Rails会自动更新匹配模式* _count的任何列与相应关联的计数。您可以使用第三个查询User.select ...作为类方法或范围来提取顶级用户。将限制(1)添加到链的末尾以仅获取顶级用户。 – 2012-07-17 04:40:00