カウント
こんなコードを書いた
before24h = (Time.now - (60 * 60 * 24)).strftime("%Y-%m-%d %H:%M:%S") # [[2, 4], [nil, 18], [1, 34]] といった [user_id, count] の配列が返る counts = Item.count( :group => :user_id, :conditions => "updated_on > '#{before24h}'" ) # 登録数の多い順にソートし、 # user_id が nil (anonymous ユーザー) のを除き、 # 20件だけとり、 # ユーザーを引っ張ってくる。 @active_users = counts.sort{|a,b| b[1] <=> a[1] }.select{|e| e[0]}[0..20].map{|e| [User.find(e[0]), e[1]] }
ぜってー inject が使えるって直感でわかるのだが「考えるのをやめた」。挑戦を待つ!(コード読めなくなるから採用しないけど)
追記:
counts = Item.count(:group => :user_id, :conditions => ["updated_on > ?", (Time.now - (60 * 60 * 24))]) @active_users_counts = counts.select{|e| e[0]}.sort_by{|e| -e[1]}[0..20].map{|e| [User.find(e[0]), e[1]] }
conditions に Time オブジェクト突っ込むのと sort_by 使ってみた。user とカウントの組が欲しいんだけど、ActiveRecord#count で工夫すれば一発でとれるのかしら?
:group と :conditions と :include と :order と :limit と掛け合わせると全体のカウントしかとれなかったんだけどなぁ。:in で突っ込むのはー、んーと、zip の逆ってどうやるんだっけ?
追記:
@active_users_counts = Item.count( :group => :user_id, :order => "count(*) desc", :limit => 20, :conditions => [ "(updated_on > ?) AND (user_id is not NULL)", (Time.now - (60 * 60 * 24)) ] ).map{|e| [User.find(e[0]), e[1]] }
user_id とカウントの組まで取れた。あと user が取れればいいんだけど。