Rails 6 adds Active Record Relation#pick


Before Rails 6, loading only the first value from the set of records was not very straight forward.

Suppose we want to fetch the name of the the first book published by author Behrouz A. Forouzan.

Book.includes(:author).where(authors: {name: 'Behrouz A. Forouzan'}).order(:published_on).limit(1).pluck(:name).first
# SELECT "books"."name" 
# FROM "books" 
# LEFT OUTER JOIN "authors" ON "authors"."id" = "books"."author_id" 
# WHERE "authors"."name" = ? 
# ORDER BY "books"."published_on" ASC 
# LIMIT ?  [["name", "Behrouz A. Forouzan"], ["LIMIT", 1]]
 => "Data Communication and Networking"

In order to load just single column value in the above case, we need to add limit(1) and first along with pluck.

pick method

Rails 6 has added ActiveRecord::Relation#pick to pick the first value from the named column in the relation.

pick is useful when we have a relation which is already narrowed down to a single row as the method applies limit(1) on the relation internally.

Book.includes(:author).where(authors: {name: 'Behrouz A. Forouzan'}).order(:published_on).pick(:name)
# SELECT "books"."name" 
# FROM "books" 
# LEFT OUTER JOIN "authors" ON "authors"."id" = "books"."author_id" 
# WHERE "authors"."name" = ? 
# ORDER BY "books"."published_on" ASC 
# LIMIT ?  [["name", "Behrouz A. Forouzan"], ["LIMIT", 1]]
 => "Data Communication and Networking"
 

As observed in the above query, pick only loads the actual value, not the entire record object similar to pluck.

Also, the value is typecast by the column type.

pick method with multiple columns

This method can also be used to get multiple columns of the relation efficiently. We can change the above query to include published_on in the result set.

# Book.includes(:author).where(authors: {name: 'Behrouz A. Forouzan'}).order(:published_on).pick(:name, :published_on)
# SELECT "books"."name", "books"."published_on" 
# FROM "books" LEFT OUTER JOIN "authors" 
# ON "authors"."id" = "books"."author_id" 
# WHERE "authors"."name" = ? 
# ORDER BY "books"."published_on" ASC 
# LIMIT ?  [["name", "Behrouz A. Forouzan"], ["LIMIT", 1]]
 => ["Data Communication and Networking", Fri, 01 Dec 2000]