Ruby Enumerable#group_by を使ってみた
DB から取得したデータを Ruby 上でグルーピングしたくてドキュメントを漁っていたら見つけたので紹介。
経緯
DB に入っている
id | task_type_id | task_id |
---|---|---|
1 | 1 | 1 |
2 | 1 | 2 |
3 | 1 | 3 |
4 | 2 | 4 |
5 | 2 | 5 |
6 | 2 | 6 |
こんな感じでデータを
[ { task_type_id: 1, task_id: [1, 2, 3] }, { task_type_id: 2, task_id: [4, 5, 6] } ]
こんな感じにタスクの種別に紐付いているタスクの一覧 JSON を Ruby で作りたかった。 task_type_id でグルーピングされた値が取れれば と思い、繰り返し関係を提供している Enumerable モジュールのドキュメントを漁った。
結果
案の定欲しいメソッドはあった。メソッド名見た瞬間、「これ!」ってなった。
instance method Enumerable#group_by (Ruby 2.2.0)
使い方
# DB から取得したデータ records = [ { id: 1, task_type_id: 1, task_id: 1 }, { id: 2, task_type_id: 1, task_id: 2 }, { id: 3, task_type_id: 1, task_id: 3 }, { id: 4, task_type_id: 2, task_id: 4 }, { id: 5, task_type_id: 2, task_id: 5 }, { id: 6, task_type_id: 2, task_id: 6 } ] records.group_by { |record| record[:task_type_id] } # => {1=>[{:id=>1, :task_type_id=>1, :task_id=>1}, {:id=>2, :task_type_id=>1, :task_id=>2}, {:id=>3, :task_type_id=>1, :task_id=>3}], 2=>[{:id=>4, :task_type_id=>2, :task_id=>4}, {:id=>5, :task_type_id=>2, :task_id=>5}, {:id=>6, :task_type_id=>2, :task_id=>6}]}
ということで、task_type_id でグルーピングされた値を取得することができた。
後はデータの形式を求めている形に変換すれば完了
records.group_by { |record| record[:task_type_id] } .map { |k, v| { task_type_id: k, task_id: v.map { |e| e[:id] } } }
(group_by の後の map が分かりづらい気がする…。また考えよう。)