Railsの技: pluckはActive RecordモデルでもEnumerableでも使える(翻訳)
Railsには、これはレコードからデータのサブセットを(訳注: 配列として)取り出せるpluck
という素晴らしく表現力の大きいメソッドがあります。Active Recordモデルのカラムを1個または数個取り出すのにpluck
を使えます。
しかし、昔からある標準的なEnumerable
に同じpluck
メソッドを用いて、指定のキーに対応する値をすべて取り出すこともできます。
pluck
の使い方
Railsでは、以下のようにpluck
でカラムのサブセットにクエリをかけられます。
Shoe.all.map(&:name)
# SELECT "shoes.*" from "shoes"
# => ["Air Force 1", "NMD_2", "Air Jordans", ... ]
# すべての靴の名前を含む配列を返すが、データベースクエリは`shoes`テーブルのすべてのカラムを取得している
Shoe.pluck(:name)
# SELECT "shoes.name" from "shoes"
# => ["Air Force 1", "NMD_2", "Air Jordans", ... ]
# 上と同じ結果になるが、欲しいカラムだけを取り出すクエリをかける
Shoe.pluck(:name, :brand)
# SELECT "shoes"."name", "shoes"."brand" FROM "shoes"
# => [["Air Jordan 1 Mid", "Nike"], ["Air Jordan 1 Mid", "Nike"], ... ]
Shoe.distinct.pluck(:brand)
# SELECT DISTINCT "shoes"."brand" FROM "shoes"
# => ["Nike", "Adidas", ... ]
ActiveSupport
が有効になっていれば、以下のようにEnumerable
でもpluck
を使えます。
[
{ id: 1, name: "David" },
{ id: 2, name: "Rafael" },
{ id: 3, name: "Aaron" }
].pluck(:name)
# => [ "David", "Rafael", "Aaron" ]
このEnumerable
版pluck
は、特に外部APIから取得したJSONデータを扱うときに重宝することがわかってきました。
require "httparty"
require "active_support"
require "active_support/core_ext"
response = HTTParty.get('http://api.stackexchange.com/2.2/questions?site=stackoverflow')
questions = JSON.parse(response.body)["items"]
questions.pluck("title")
# => [
# "JavaScript to Python - Interpreting JavasScript .filter() to a Python user",
# "Nuxt generate and firebase gives timer warning",
# "Variable expected error when I increment the value of a map",
# ...
# ]
pluck
が最もよく使われるのはハッシュですが、渡したメッセージに応答できるオブジェクト(通常のオブジェクトやStructも含む)なら何でもpluck
を使えるようになります。
今後、値を1個取り出すのにmap
を呼ぼうとしていることに気づいたら、pluck
に切り替えてコードを改善できるかどうか試してみましょう。
関連リソース
- Rails APIドキュメント:
ActiveRecord#pluck
-
Rails APIドキュメント:
Enumerable#pluck
概要
原著者の許諾を得て翻訳・公開いたします。
日本語タイトルは内容に即したものにしました。