我想在我的应用中创建一个过去一个月创建的用户的简单图表。就像过去一个月中的每一天一样,我想显示当天注册的用户数。到目前为止我所拥有的:
# 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天内遍历每一天并显示当天创建的用户数量?
答案 0 :(得分: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 :(得分: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
答案 2 :(得分: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的默认值,给了我一个在缺少值时获得零的简洁方法。