Ruby on Rails: pluck x select x map
--
I’m writing this short article to clarify a few questions about Active Record vs Ruby methods to manipulate data coming from the database.
I'll start with some straightforward cases. Let's suppose you're looking for a list of emails from our user accounts. There are several ways you can achieve the same outcome. We'll start with the pluck method.
About :pluck, from Active Record
Account.all.pluck(:email)
# triggered query
SELECT "accounts"."email" FROM "accounts"
# returned values
=> ["admin_arthur@doctolib.com",
"ivan@doctolib.com",
"jessy@doctolib.com"]
Using pluck will retrieve the names from users and return them in an array of strings. No unused columns. No model initialization. For this use case, pluck is hands down the best choice, but let's deep dive into select too.
About :select, from Active Record
Here's where the confusion often starts. There's also a select
method in Ruby, which can be used to filter items of a collection based on a certain condition. This is not the same as the select
method from ActiveRecord which specifies the columns of a table to be selected.
Account.all.select(:email)
# triggered query
SELECT "accounts"."email" FROM "accounts"
# apparent returned values - but not really 🤔
=> [#<Account:0x00000001545f34f8 id: nil, email: "romchoq@doctolib.com">,
#<Account:0x0000000157338670 id: nil, email: "flav@doctolib.com">,
#<Account:0x00000001573385d0 id: nil, email: "jessy@doctolib.com">]
So here's the first gotcha. If you run the above command in your rails console, one might think that the select
method is triggering a database query (that's false!), and returning an array of Accounts (also false!) that contains uniquely the specified attributes.
That's what it seems from the console result, but it's only the case because the console is printing the result of your command. It's the same as:
p Account.all.select(:email)
# triggered query
SELECT "accounts"."email" FROM "accounts"
# returned values
=> [#<Account:0x00000001545f34f8 id: nil, email: "romchoq@doctolib.com">,
#<Account:0x0000000157338670 id: nil, email: "flav@doctolib.com">…