Rails 6.1 add Enumerable#pick to complement Relation#pick


With Rails 6.0

Initially pick was available only for a relation when it was introduced in Rails 6.

ChipManufaturer.pick(:name)
# SELECT chip_manufacturers.name FROM chip_manufacturers LIMIT 1
# => "AMD"

ChipManufaturer.pick(:name, :product)
# SELECT chip_manufacturers.name, chip_manufacturers.product FROM chip_manufacturers LIMIT 1
# => [ "AMD", "Ryzen" ]

ChipManufaturer.where(product: "Xeon").load.pick(:name, :product)
# SELECT chip_manufacturers.name, chip_manufacturers.product FROM chip_manufacturers
# WHERE chip_manufacturers.product = $1  [["product", "Xeon"]]
# => [ "Intel", "Xeon" ]

Looking at the above queries we can understand that it picks the value from a named column in the current relation.

It can be used as a shorthand for ChipManufaturer.limit(1).pluck(:name).first. The best part about pick is it only loads the actual value and not the entire record like pluck which is more efficient. And it is also typecasts by column type like pluck.

With Rails 6.1

Rails 6.1 allows pick to be called on the object that could either be an enumerable or a relation.

Let’s consider an Array of Hash as shown in the example below.

  [{ name: "AMD" }, { name: "NVIDIA" }, { name: "Intel" }].pick(:name)
  #   # => "AMD"
  #
  [{ name: "AMD", product: "Ryzen" }, { name: "Intel", product: "Xeon"}].pick(:name, :product)
  #   # => [ "AMD", "Ryzen" ]

As shown in the above example pick extracts the value of the first element with key name or name and product. It acts similar to pluck(:name).first.

This is useful to be able to call pick on loaded relations, unloaded relations, and plain enumerables interchangeably.