Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

Railsの技: pluckはActive RecordモデルでもEnumerableでも使える(翻訳)

概要

原著者の許諾を得て翻訳・公開いたします。

日本語タイトルは内容に即したものにしました。

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" ]

このEnumerablepluckは、特に外部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の技: cycleメソッドでビューのループの「i%2==0」を避ける(翻訳)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。