On Jan 3, 2011, at 7:32 PM, Dandan wrote:
> 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
> ------
> data=[]
> start_date = Date.today-1month
> end_date = Date.today
>
> results = User.find(:all,:select => 'created_at', conditions =
> {:created_at => start_date..end_date}).group_by{|u|
> u.created_at.to_date}.sort
>
> #go through each date between start and end date and add 0 for missing
> days
> start_date.upto(end_date) do |date|
> result = results.find{|r| r[0]==date}
> users_count = result.nil? ? 0 : result[1].count
> data << [date.strftime("%d %b"), users_count]
> end
> -----
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/
--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To post to this group, send email to rubyonrails-talk@googlegroups.com.
To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
No comments:
Post a Comment