Tip: Pluck single values out of ActiveRecord models or Enumerables
Rails has a great, expressive term called pluck
that allows you to grab a subset of data from a record. You can use this on ActiveRecord models to return one (or a few) columns.
But you can also use the same method on regular old Enumerables
to pull out all values that respond to a given key.
Usage
In Rails, use pluck
to query a subset of columns.
Shoe.all.map(&:name)
# SELECT "shoes.*" from "shoes"
# => ["Air Force 1", "NMD_2", "Air Jordans", ... ]
# This returns an array with all shoe names, but our database query pulled down all of the columns on the `shoes` table
Shoe.pluck(:name)
# SELECT "shoes.name" from "shoes"
# => ["Air Force 1", "NMD_2", "Air Jordans", ... ]
# Same result, but we only query exactly the columns we wanted
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", ... ]
You can also use pluck
with Enumerables
when using ActiveSupport
:
[
{ id: 1, name: "David" },
{ id: 2, name: "Rafael" },
{ id: 3, name: "Aaron" }
].pluck(:name)
# => [ "David", "Rafael", "Aaron" ]
I find the Enumerable
version to be particularly handy when dealing with JSON data from external APIs.
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",
# ...
# ]
While pluck
is most often used with Hashes, you can use it with any object that responds to the message you pass in – including regular Ruby objects or Structs.
Next time you find yourself calling map
to get back a single value, see if your code might be improved by switching to pluck
.
Additional Resources
Rails API Docs: ActiveRecord#pluck
Rails API Docs: Enumerable#pluck