Rails で Active Record のデータを キーが id, 値が Active Record であるような Hash を作る方法を備忘録として残しておく

環境

  • ruby: 3.0.4
  • rails: 6.1.0

実際のコード

index_by, inject, pluck + to_h メソッドのいずれかを使用する

前提

データの登録状態

id book_id name
1 1 少年誌
2 1 青年誌
3 1 ビジネス
4 1 自己啓発

[Rails Console]

categories = Category.all.index_by(&:id)

#=> {
#=>  1=>
#=>   #<Category:0x0000562b92c5fcb0
#=>    id: 1,
#=>    book_id: 1,
#=>    name: "少年誌",
#=>    created_at: Wed, 24 Aug 2022 02:54:05.711796000 UTC +00:00,
#=>    updated_at: Wed, 24 Aug 2022 02:54:05.711796000 UTC +00:00>,
#=>  2=>
#=>   #<Category:0x0000562b92c97160
#=>    id: 2,
#=>    book_id: 1,
#=>    name: "青年誌",
#=>    created_at: Wed, 24 Aug 2022 02:54:45.283884000 UTC +00:00,
#=>    updated_at: Wed, 24 Aug 2022 02:54:45.283884000 UTC +00:00>,
#=>  3=>
#=>   #<Category:0x0000562b92c97098
#=>    id: 3,
#=>    book_id: 2,
#=>    name: "ビジネス",
#=>    created_at: Wed, 24 Aug 2022 03:13:14.155937000 UTC +00:00,
#=>    updated_at: Wed, 24 Aug 2022 03:13:14.155937000 UTC +00:00>,
#=>  4=>
#=>   #<Category:0x0000562b92c96f80
#=>    id: 4,
#=>    book_id: 2,
#=>    name: "自己啓発",
#=>    created_at: Wed, 24 Aug 2022 03:13:21.284702000 UTC +00:00,
#=>    updated_at: Wed, 24 Aug 2022 03:13:21.284702000 UTC +00:00>
#=> }

index_by メソッドの引数はブロックなのでキーの加工も可能

categories = Category.all.index_by { |c| "category_#{c.id}" }

#=> {
#=>  "category_1"=>
#=>   #<Category:0x0000562b9325f598
#=>    id: 1,
#=>    book_id: 1,
#=>    name: "少年誌",
#=>    created_at: Wed, 24 Aug 2022 02:54:05.711796000 UTC +00:00,
#=>    updated_at: Wed, 24 Aug 2022 02:54:05.711796000 UTC +00:00>,
#=>  "category_2"=>
#=>   #<Category:0x0000562b9325f4d0
#=>    id: 2,
#=>    book_id: 1,
#=>    name: "青年誌",
#=>    created_at: Wed, 24 Aug 2022 02:54:45.283884000 UTC +00:00,
#=>    updated_at: Wed, 24 Aug 2022 02:54:45.283884000 UTC +00:00>,
#=>  "category_3"=>
#=>   #<Category:0x0000562b9325f3e0
#=>    id: 3,
#=>    book_id: 2,
#=>    name: "ビジネス",
#=>    created_at: Wed, 24 Aug 2022 03:13:14.155937000 UTC +00:00,
#=>    updated_at: Wed, 24 Aug 2022 03:13:14.155937000 UTC +00:00>,
#=>  "category_4"=>
#=>   #<Category:0x0000562b9325f318
#=>    id: 4,
#=>    book_id: 2,
#=>    name: "自己啓発",
#=>    created_at: Wed, 24 Aug 2022 03:13:21.284702000 UTC +00:00,
#=>    updated_at: Wed, 24 Aug 2022 03:13:21.284702000 UTC +00:00>
#=> }

value の方も加工したい場合には inject メソッドを使用する

categories = Category.all.inject({}) do |hash, c|
  hash[c.id] = c.name
  hash
end

#=> {1=>"少年誌", 2=>"青年誌", 3=>"ビジネス", 4=>"自己啓発"}

ちなみに上記のような出し方がしたいのであれば下記でも良い

categories = Category.all.pluck(:id, :name).to_h

#=> {1=>"少年誌", 2=>"青年誌", 3=>"ビジネス", 4=>"自己啓発"}