Fernando
Fernando

Reputation: 325

Rails Group by inside Group by

I need to group my ActiveRecords first by YEAR and then by MONTH, something like this:

{2017=>
    "January"=>
        [Record1, record2, etc]
    "February"=>
        [Record1, record2, etc]
 2016=>
    "January"=>
        [Record1, record2, etc]
    "February"=>
        [Record1, record2, etc]
}

and so on...

I tried to use

.group_by( |a| [a.year, a.month] ) 

but the best I could get was:

{[2017, "January"]=>
        [Record1, record2, etc]
 [2017,"February"]=>
        [Record1, record2, etc]
 [2016, "January"]=>
        [Record1, record2, etc]
 [2016,"February"]=>
        [Record1, record2, etc]
}

Thanks

PS: I have column named YEAR and MONTH in my model.

PS2: I use Ruby 2.3 and Rails 4.2

Upvotes: 0

Views: 1422

Answers (3)

ehoffmann
ehoffmann

Reputation: 798

.group_by(&:year).each_with_object({}) {|(k, v), h| h[k] = v.group_by(&:month) }

Will give you what you want:

{ 2017 => { 
    "January" => [record1, record2, etc], 
    "February" => [record1, record2, etc] 
  },
  2016 => {
...

So

results[2017]['January'] #=> [record1, record2, etc]

Upvotes: 5

Amit Choudhary
Amit Choudhary

Reputation: 31

You can try this

Model.all.inject({}) do |hash, record|
  hash[record.year] = Hash.new { |h, k| h[k] = [] }
  hash[record.year][record.month] << project
  hash
end

Upvotes: 0

Ronan Lopes
Ronan Lopes

Reputation: 3398

You could do nested group_by. Something like:

Model.group_by(:year) do |year, objects|
   objects.group_by(&:month) do |month, objects|
    //Do the actions you need for that objects
   end
end

Don't know if there's a more efficient way (or less verbose) to do that, but think this works. Give a try!

Upvotes: 1

Related Questions