How to Loop through Months in Ruby on Rails

loops, ruby, ruby-on-rails, ruby-on-rails-3

Solution

First, count the number of months between two dates (courtesy of Massimiliano Peluso):

start_date = 13.months.ago.to_date
# => Wed, 16 Nov 2011

end_date = Date.today
# => Sun, 16 Dec 2012

number_of_months = (end_date.year*12+end_date.month)-(start_date.year*12+start_date.month)
# => 13

Then from the start month, counting each month thereafter, find the first/last dates and append to an accumulator array.

dates = number_of_months.times.each_with_object([]) do |count, array|
  array << [start_date.beginning_of_month + count.months,
            start_date.end_of_month + count.months]
end
# => ...

Now `dates` will contain an array with nested `Date` pairs corresponding to the first and last date of each month. This `dates` array will be easy to iterate for processing.

dates
# => [[Tue, 01 Nov 2011, Wed, 30 Nov 2011], [Thu, 01 Dec 2011, Fri, 30 Dec 2011], ...

dates[0].first
# => Tue, 01 Nov 2011

dates[0].last
# => Wed, 30 Nov 2011

dates[0].last.class
# => Date

This is tested and working in Rails 3.2.5/Ruby 1.9.3p194

Problem

I need to loop through several months in a Ruby on Rails application. For each month, I need to find the first and last day of that given month. These dates are then used in a separate query to find events occurring during those dates and running calculations on them. Initially, I tried something like: ``` (11.months.ago.to_date.month..Date.today.month).each do |m| start_date = '01-#{m}-#{Date.today.year}'.to_date.beginning_of_month end_date = '01-#{m}-#{Date.today.year}'.to_date.end_of_month end ``` Of course, the year isn't updated in this case in the event that 11 months ago involves going back to the previous year. And, I don't think this type of for/each loop works. I also tried mapping the numbers to an array and using the same method, but received an error. What's the best way to accomplish something like this?

Original source

Related problems