2010-01-11 44 views
3

我想製作一個簡單的在過去一個月內在我的應用中創建的用戶圖表。就像過去一個月的每一天基本一樣,我想顯示那天註冊的用戶數。我有什麼至今:在給定的月份內每天通過`created_at`獲取元素的數量

# Controller 
@users = User.count(:order => 'DATE(created_at) DESC', :group => ["DATE(created_at)"]) 

# View 
<% @users.each do |user| %> 
    <%= user[0] %><br /> 
    <%= user[1] %> 
<% end %> 

# Output 
2010-01-10 2 
2010-01-08 11 
2010-01-07 23 
2010-01-02 4 

這是確定的,但如果沒有用戶是在某一天創建的,它應該說是「0」,而不是不是那裏。我如何循環過去30天的每一天,並顯示當天創建的用戶數量?

回答

4

我想分離勝過最小性能提升這裏:

# Controller 
@users = User.all(:conditions => ["created_at >= ?", Date.today.at_beginning_of_month]) 

# View 
Date.today.at_beginning_of_month.upto(Date.today).each do |date| 
    <%= date %>: <%= @users.select{|u| u.created_at == date }.size %> 
end 
+1

似乎對我來說看起來太多邏輯了。我認爲操縱屬於控制器 - 預處理似乎比「選擇30次」更好。 – Emily 2010-01-11 20:32:46

+0

select是視圖中唯一的附加邏輯,它可以保存控制器4行。我的首要任務是永遠瘦骨碌的控制器。你對所有的選擇絕對正確,但如果這真的是一個性能問題,我會爲User添加一個方法,將邏輯放在SQL中。類似User.new_accounts_per_day。但是SQL很難。但從來沒有在控制器。 – tfwright 2010-01-11 20:48:24

+0

最多我會在視圖中放入「|| = 0」部分,但肯定會將計數保存在帶有SQL的控制器中。這會給你在控制器中的一行代碼(精簡)和有效的計數。你的實現將是O(@ users.size),並且即使是小型數據集也可能慢100倍。 – klochner 2010-01-11 21:52:24

8
date = Date.today-30 

# Controller 
@users = User.count(:conditions=>["created_at >= ?", date], :order => 'DATE(created_at) DESC', :group => ["DATE(created_at)"]) 
date.upto(Date.today) do |x| 
    @users[x.to_s] ||= 0 
end 
@users.sort! 

# View 
<% @users.each do |user| %> 
    <%= user[0] %><br /> 
    <%= user[1] %> 
<% end %> 
+1

你想@ users.sort! – klochner 2010-01-11 18:01:49

+0

,使用'@ users.each do | date,count | 。 。 「。 – klochner 2010-01-11 18:04:22

+0

他們不會被排序嗎?我們在查找器中使用了':order'。 – 2010-01-11 18:05:34

3

由於@floyd較早評論,代碼做SELECT所屬的模型:

class User < ActiveRecord::Base 
    def self.count_new_users_per_day(cutoff_at) 
    result = count(:all, :conditions => ["created_at >= ?", cutoff_at], 
         :group => "DATE(created_at)") 
    # See http://ruby-doc.org/core-1.8.7/classes/Hash.html#M000163 
    result.default = 0 
    result 
    end 
end 

的控制器執行邏輯並調用模型層:

class UsersController < ActionController::Base 
    def index 
    @cutoff_at = 30.days.ago.at_midnight 
    @new_users_by_date = User.count_new_users_per_day(@cutoff_at) 
    @dates = ((@cutoff_at.to_date) .. (@cutoff_at.to_date >> 1)) 
    end 
end 

和視圖僅用於顯示數據控制器的爲它設置負責:

# Chose to move the code to a partial 
<%= render :partial => "user_count", :collection => @dates, :as => :date %> 

# _user_count.html.erb 
<td><%=h date.to_s(:db) %></td> 
<td><%= number_with_delimiter(@new_users_by_date[date.to_s(:db)]) %></td> 

基本上,因爲SQL將不會返回缺少的日期,你必須遍歷全套日期自己的,並詢問Hash/ResultSet是否具有正確的值。在上面的模型實現中,我在事實之後設置了Hash的默認值,給了我一個乾淨的方法,以便在缺少值時獲得零。

相關問題