Jan
Jan

Reputation: 6828

Ruby group by month and year

I have an (ar) class PressClipping consisting of a title and a date field.

I have to display it like that:

2011 February
title1
title2
...
2011 January
...

What is the easiest way to perform this grouping?

Upvotes: 2

Views: 3119

Answers (1)

Phrogz
Phrogz

Reputation: 303224

Here's some Haml output showing how to iterate by using Enumerable#group_by:

- @clippings_by_date.group_by{|c| c.date.strftime "%Y %b" }.each do |date_str,cs|
  %h2.date= date_str
  %ul.clippings
    - cs.each do |clipping|
      %li <a href="...">#{clipping.title}</a>

This gives you a Hash where each key is the formatted date string and each value is an array of clippings for that date. This assumes Ruby 1.9, where Hashes preserve and iterate in insertion order. If you're under 1.8.x, instead you'll need to do something like:

- last_year_month = nil
- @clippings_by_date.each do |clipping|
  - year_month = [ clipping.date.year, clipping.date.month ]
  - if year_month != last_year_month
    - last_year_month = year_month
    %h2.date= clipping.date.strftime '%Y %b'
  %p.clipping <a href="...>#{clipping.title}</a>

I suppose you could take advantage of group_by under 1.8 like so (just using pure Ruby now to get the point across):

by_yearmonth = @clippings_by_date.group_by{ |c| [c.date.year,c.date.month] }
by_yearmonth.keys.sort.each do |yearmonth|
  clippings_this_month = by_yearmonth[yearmonth]
  # Generate the month string just once and output it
  clippings_this_month.each do |clipping|
    # Output the clipping
  end 
end

Upvotes: 7

Related Questions