Although it doesn’t seem to be well known, Ruby hashes have a “default value” feature that will help you do what you want in a better way. Another way of expressing what you’re trying to do is this:
Create a hash that gives 0 for any key within my data range unless I have stored some other value under that key.
You can accomplish exactly this using a block to establish the default value of the hash:
@data = Hash.new do |h, key|
if (date1..date2).include?(key)
0
else
nil
end
end
Or, more succinctly:
@data = Hash.new {|h, key| (date1..date2).include?(key) ? 0 : nil }
Then load your data from the database and merge it into this hash:
@data.merge! User.where(…).group(…).count
Note: Your order() is irrelevant because you are grouping. It will probably get optimized away, but you can simply leave it off and get the same result.
Now if you do @data[foo]:
- if foo is not comparable to a date you will get
nil
- if foo is outside the date range you will get
nil
- if foo is within the date range but no data was returned by your query you will get
0
- if foo is a date with data in the database you will get the correct count
This method is preferable to pre-loading the hash because it will work efficiently (in time and space) even for very large date ranges. And arguably it is more straightforward too.