複数の要素でgroupし、countした結果を整形したい。


以下のようなテーブルがあり、

create_table "subtasks", force: true do |t|
  t.integer  "task_id",                              null: false
  t.integer  "product_id",                           null: false
end

以下のコードを実行すると

SubTask.all.group(:product_id, :task_id).count

以下のような結果が得られるとする、

{[1, 1]=>3, [1, 2]=>5, [2, 3]=>5, [3, 4]=>3}

しかし、以下のような結果が欲しい。

{1=>{1=>3, 2=>5}, 2=>{3=>5}, 3=>{4=>3}}

この場合は、以下のようにreduceを使うことで実現は可能。

SubTask.all.group(:product_id, :task_id).count.reduce({}) do |result, (key, value)|
  product_id, task_id = key
  result[product_id] ||= {}
  result[product_id][task_id] = value
  result
end

よりシンプルに書く方法ががありましたら、ご教授ください。

see also