I would like to count the number of users created each day. The
problem arises that on some days no users a created so there are gaps
in my array of users created by day. E.g.
I've written the following code which successfully works but I'm
wondering if it can be done better as I am also wanting to sort users
by month.
So first: can it be written better
Second(if you've got time) : how would you write to get users created
in a month
First, let me fake your results. Note that this does not bother to .sort since the .group_by will be a hash and that's just as easy to work with.
on14th = Date.civil(2011, 1, 14)
on15th = Date.civil(2011, 1, 15)
on17th = Date.civil(2011, 1, 17)
results = [ on17th, on15th, on14th, on15th, on17th, on15th, on14th, on15th, ].group_by{|u| u}
Use the << method of a Date to go back a month:
end_date = Date.civil(2011,2,1)
start_date = end_date << 1
Get the set of dates the simplest way possible. (Note that for large ranges this may be less practical.)
date_range = (start_date .. end_date).to_a
Then just map that range to the results you want.
data = date_range.map {|d| [d.strftime("%d %b"), results.fetch(d,).size] }
You might also just get the counts from the database directly:
results = User.find(:all,
:select => 'DATE(created_at) as create_date, COUNT(*) as user_count',
:conditions => { :created_at => start_date..end_date },
:group => 'DATE(created_at)').
map{|u| [Date.parse(u.create_date), u.user_count.to_i]}
data = date_range.map {|d| [d.strftime("%d %b"),
(results.assoc(d) || [nil,0])[1]] }
You might also just get the counts from the database directly:
results = User.find(:all,
:select => 'DATE(created_at) as create_date, COUNT(*) as
user_count',
:conditions => { :created_at => start_date..end_date },
:group => 'DATE(created_at)').
map{|u| [Date.parse(u.create_date), u.user_count.to_i]}
data = date_range.map {|d| [d.strftime("%d %b"),
(results.assoc(d) || [nil,0])[1]] }
You might also just get the counts from the database directly:
results = User.find(:all,
:select => 'DATE(created_at) as create_date, COUNT(*) as
user_count',
:conditions => { :created_at => start_date..end_date },
:group => 'DATE(created_at)').
map{|u| [Date.parse(u.create_date), u.user_count.to_i]}
data = date_range.map {|d| [d.strftime("%d %b"),
(results.assoc(d) || [nil,0])[1]] }
Or better yet, use User.count instead of .find .
But the OP wanted counts by day, not a single total.