141

Here are two sample codes.

First one with collect:

User.first.gifts.collect(&:id)

Second one with pluck:

User.first.gifts.pluck(:id)

Is there any difference between them in performance or something else?

ekremkaraca
  • 1,453
  • 2
  • 18
  • 37
Mohit Jain
  • 43,139
  • 57
  • 169
  • 274

6 Answers6

252

pluck is on the db level. It will only query the particular field. See this.

When you do:

 User.first.gifts.collect(&:id)

You have objects with all fields loaded and you simply get the id thanks to the method based on Enumerable.

So:

  • if you only need the id with Rails 4, use ids: User.first.gifts.ids

  • if you only need some fields with Rails 4, use pluck: User.first.gifts.pluck(:id, :name, ...)

  • if you only need one field with Rails 3, use pluck: User.first.gifts.pluck(:id)

  • if you need all fields, use collect

  • if you need some fields with Rails 4, still use pluck

  • if you need some fields with Rails 3, use selectand collect

apneadiving
  • 114,565
  • 26
  • 219
  • 213
  • "if you need some fields, use selectand collect" - can't you just use `pluck` with multiple attributes, like `pluck(:id, :name)`? – Alexander Popov Dec 10 '14 at 15:03
  • @AlexPopov - Rails 4+ supports ```pluck```ing multiple fields, Rails 3 does not, unless you use [Ryan Lefevre's workaround](http://meltingice.net/2013/06/11/pluck-multiple-columns-rails/) – marksiemers Mar 27 '15 at 14:07
  • 3
    In Rails 4, if you *only* need the `id`, use `.ids` Ref doc: http://api.rubyonrails.org/classes/ActiveRecord/Calculations.html#method-i-ids – Ivan Chau Mar 29 '15 at 15:52
36

Yes. According to Rails guides, pluck directly converts a database result into an array, without constructing ActiveRecord objects. This means better performance for a large or often-running query.

In addition to @apneadiving's answer, pluck can take both single and multiple column names as argument:

Client.pluck(:id, :name)
# SELECT clients.id, clients.name FROM clients
# => [[1, 'David'], [2, 'Jeremy'], [3, 'Jose']]
ekremkaraca
  • 1,453
  • 2
  • 18
  • 37
Fellow Stranger
  • 32,129
  • 35
  • 168
  • 232
4

The basic and main difference is that Pluck applies on db level and collect get all data and then return record to you when you need all records use collect and when few fields then use pluck

bluehallu
  • 10,205
  • 9
  • 44
  • 61
Thorin
  • 2,004
  • 1
  • 19
  • 30
4

Late to the party, but if you would like a deeper pluck you can use includes:

User.all.includes(:groups).pluck("users.id", "users.name", "groups.id", "groups.name")

This results in a bigger array like

[
  [12, "Sam", 4, "FriendsRUs"],
  ...
]
Yoko
  • 793
  • 10
  • 19
3

If there is a case where you are using few attributes of the retrieved record. In such cases you should use pluck .

User.collect(&:email)

In above example if you only need email attribute than you are wasting memory and time. Because it will retrieve all the columns from user table in the database, allocates the memory for each attributes (including the attributes which you will never use)

NOTE: pluck does not return ActiveRecord_Relation of the user

Chimed Palden
  • 125
  • 1
  • 8
1

The main difference between collect and pluck is that collect loads all the attributes from DB while pluck loads only the attributes you have mentioned. For example, when you do:

User.all.collect(&:id)

this loads all the attributes of User records in memory and returns the ids. And when you do:

User.all.pluck(:id)

this loads only the ids in memory so it is more efficient in case you need to access only few attributes.

Sachin Singh
  • 993
  • 8
  • 16