adding missing days to array of users created by day

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.

[ ['14 Jan', 2], ['15 Jan', 4], ['17 Jan', 2] ] # [day, users created]

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]] }

-Rob

Rob Biedenharn Rob@AgileConsultingLLC.com http://AgileConsultingLLC.com/ rab@GaslightSoftware.com http://GaslightSoftware.com/

Rob Biedenharn wrote in post #972151: [...]

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 .

-Rob

Rob Biedenharn Rob@AgileConsultingLLC.com http://AgileConsultingLLC.com/ rab@GaslightSoftware.com http://GaslightSoftware.com/

Best,

Rob Biedenharn wrote in post #972151: [...]

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.

-Rob

Rob Biedenharn wrote in post #972262:

                            (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.

Right. That's what count with :group is for.

-Rob

Best,