Rails Pluck vs Select and Map/Collect

In Rails, Pluck vs Select can be understood while active record querying. Pluck is used to get an array of particular attribute based on particular condition. Same can be obtained using select and then collect on a model. This tutorial will help you understand the difference between these ways of collecting specific attribute values.

We will start with an example to understand this.

When you want to select ids users having age greater than let us say 20, then in standardized query language this can be written as,

select id from users where age > 20;

But, if you want to do it in Rails way then,

Option 1 - Collect
User.where('age > 20').select(:id).collect(&:id)
Option 2 - Map
User.where('age > 20').select(:id).map(&:id)
Option 3 - Pluck
User.where('age > 20').pluck(:id)

Let us see the what does these approaches exactly infer.

Collect/Map

Basically, these 2 methods are aliases of each other. Thus, they do one and the same thing. If you want to know more about collect/map, you can refer the post on Collect/Map.

  • Collection of ActiveRecords is returned by querying the database
  • Then, Loop is run on this collection to collect the ids from the collection of active record
Pluck
  • Pluck directly returns array of the attribute that we pass to it
  • It also selects only those attributes while querying
  • Thus, Rails retrieved array of attribute values instead of array of ActiveRecord
  • Thus, extra loop to get ids from the collection of ActiveRecord is saved while using the pluck method

We will use benchmarking to test the concept that we discussed.

Approach - Collect
puts Benchmark.measure {
  User.where('age > 20').select(:id).collect(&:id)
}
User Load (0.7ms)  SELECT id FROM `users` WHERE (age < 20)
0.010000   0.000000   0.010000 (  0.011173)
nil

Time Taken : 0.011173 s

Approach - Pluck
puts Benchmark.measure {
  User.where('age > 20').pluck(:id)
}
SQL (0.7ms)  SELECT `users`.`id` FROM `users` WHERE (age < 20)
0.010000   0.000000   0.010000 (  0.003422)
nil

Time Taken : 0.003422 s

Above benchmarking shows that pluck takes less time to get the required data than map.

Rails Pluck Multiple Values/Columns

You can pass multiple columns/attributes for pluck for active records querying and retrieving an array of particular attribute. This can be done as follows,

User.where('age > 20').pluck(:id, :name)

This will give you an array of arrays in which each array will contain id and name of user.

When to prefer Map over Pluck?

There are some cases where map should be preferred over pluck. For example, let’s say you already have queried and retrieved user records. In that case, you have access to array of ActiveRecord objects. Calling pluck, in that case, caused a new query to the database.

user_ids = []
users = User.where('age > 20')
users.each do |user|
  # some operation
  user_ids << user.id
end

When above code is run, it runs query on the database when users.each is called.

Now, if you try to get users age by using pluck as,

users.pluck(:age)

It causes another query to the database. This can be avoided. As query is done and we have access to array of user records in memory in the form of array of ActiveRecord objects, we need to prefer map in this case over pluck.

Conclusion

This shows that SQL query executed in both the cases is exactly the same, but time taken by pluck approach is considerably less than that of collect/map with select. This was queried on database having users around 10k. If you have very large database then the difference would matter to you when querying.

Reference

You can refer APIDock for more information of Pluck. Let us know through comments if you have any concern/feedback.

-->