개발/ROR

[RoR] Active Record Query Interface 'pluck'

팥빙구 2015. 3. 30. 11:11

pluck can be used to query single or multiple columns from the underlying table of a model.

It accepts a list of column names as argument and returns an array of values of the specified columns with the corresponding data type.


Client.where(active: true).pluck(:id)
# SELECT id FROM clients WHERE active = 1
# => [1, 2, 3]
 
Client.distinct.pluck(:role)
# SELECT DISTINCT role FROM clients
# => ['admin', 'member', 'guest']
 
Client.pluck(:id, :name)
# SELECT clients.id, clients.name FROM clients
# => [[1, 'David'], [2, 'Jeremy'], [3, 'Jose']]

pluck makes it possible to replace code like:

Client.select(:id).map { |c| c.id }
# or
Client.select(:id).map(&:id)
# or
Client.select(:id, :name).map { |c| [c.id, c.name] }

with:

Client.pluck(:id)
# or
Client.pluck(:id, :name)

Unlike selectpluck directly converts a database result into a Ruby Array, without constructing ActiveRecord objects. This can mean better performance for a large or often-running query. However, any model method overrides will not be available. For example:

class Client < ActiveRecord::Base
  def name
    "I am #{super}"
  end
end
 
Client.select(:name).map &:name
# => ["I am David", "I am Jeremy", "I am Jose"]
 
Client.pluck(:name)
# => ["David", "Jeremy", "Jose"]

Furthermore, unlike select and other Relation scopes, pluck triggers an immediate query, and thus cannot be chained with any further scopes, although it can work with scopes already constructed earlier:

Client.pluck(:name).limit(1)
# => NoMethodError: undefined method `limit' for #<Array:0x007ff34d3ad6d8>
 
Client.limit(1).pluck(:name)
# => ["David"]