✨
Rails の ActiveRecord で特定のカラムの値を Hash 形式で取得したかった
ActiveRecord で特定のカラムの値のみを取得する場合には .pluck が利用できます。
# [name, age] 形式で各レコードを取得する
pp User.pluck(:name, :age)
# => [["homu", 14], ["mami", 15], ["mado", 14]]
.pluck では [カラム1, カラム2, カラム3...] という感じでレコードごとのカラムの値を配列で返します。
が、これだと扱いづらいので { カラム1 => 値1, カラム2 => 値2... } みたいな形で受け取りたい。
ActiveRecord 側ではメソッドがなさそうだった
パッと調べた限りだとなさそうだったのでとりあえず Ruby 側でやってみた。
pp User.pluck(:name, :age).map { |name, age| { name:, age: } }
# => [{name: "homu", age: 14},
# {name: "mami", age: 15},
# {name: "mado", age: 14}]
単純に #map で Hash に置き換えただけです。
対象のカラムが少ないならこれでもいいんですがカラムの数が多くなると
pp User.pluck(:name, :age, :active, :email, :updated_at).map { |name, age, active, email, updated_at|
{ name:, age:, active:, email:, updated_at: }
}
みたいになってしまい、カラム名の重複が目立ってしまいますね…
改善した
ってことで最初に取得するカラムを定義しておいて、そこからいい感じにレコードを取得するようにしてみました。
User.create(name: "homu", age: 14, active: true, email: "homu@example.com")
User.create(name: "mami", age: 15, active: false, email: "")
User.create(name: "mado", age: 14, active: true, email: "mado@example.com")
columns = %i(name age active email updated_at)
pp User.pluck(*columns).map { |values|
columns.zip(values).to_h
}
# => [{name: "homu",
# age: 14,
# active: true,
# email: "homu@example.com",
# updated_at: 2025-08-28 11:48:48.635422 UTC},
# {name: "mami",
# age: 15,
# active: false,
# email: "",
# updated_at: 2025-08-28 11:48:48.636567 UTC},
# {name: "mado",
# age: 14,
# active: true,
# email: "mado@example.com",
# updated_at: 2025-08-28 11:48:48.63694 UTC}]
オシャレポイントは columns.zip(values).to_h している部分でこれで columns と values からいい感じに Hash に変換しています。
columns = %i(name age active email)
values = ["homu", 14, true, "homu@example.com"]
# #zip することで [:name, :age] ["homu", 14] が
# [[:name, "homu"], [:age, 14]] な配列に変換される
result = columns.zip(values)
# #to_h で [[:name, "homu"], [:age, 14]] が
# { name: "homu", age: 14 } の Hash に変換される
pp result.to_h
本当は ActiveRecord 側でこういう変換メソッドが用意されているといいんですけどね〜〜〜〜〜。
Discussion