In part of my code I need to grab users's id but pluck
doesn't grab them. Only map(&:id)
can do it. I was wondering why.
I've wrote a quick and dirty block of code to find what's happen
def remove_users user_ids
p users_to_remove.class
users_to_remove = self.users.where(id: user_ids)
if users_to_remove.present?
self.users -= users_to_remove
self.save
p users_to_remove.class
p users_to_remove
Rails::logger.info "\n#{users_to_remove}\n"
users_to_remove_map = users_to_remove.map(&:id)
p users_to_remove_map
Rails::logger.info "\nmap id: #{users_to_remove_map}\n"
users_to_remove_pluck = users_to_remove.pluck(:id)
p users_to_remove_pluck
Rails::logger.info "\npluck id: #{users_to_remove_pluck}\n"
#...
end
self.user_ids
end
Who return in my test.log
#<User::ActiveRecord_AssociationRelation:0x007fb0f9c64da8>
map id: [144004]
(0.3ms) SELECT "users"."id" FROM "users" INNER JOIN "groups_users" ON "users"."id" = "groups_users"."user_id" WHERE "groups_users"."group_id" = $1 AND "users"."id" IN (144004, 144005) [["group_id", 235819]]
pluck id: []
And in my test
User::ActiveRecord_AssociationRelation
User::ActiveRecord_AssociationRelation
#<ActiveRecord::AssociationRelation [#<User id: 144004, created_at: "2015-08-06 08:55:11", updated_at: "2015-08-06 08:55:11", email: "user_2@test.com", token: "rpf5fqf5bs1ofme6aq66fwtcz", reset_password_token: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, disabled: false, first_name: "John_2", last_name: "Rivers_4", is_owner: false, organisation_id: 235826, encrypted_password: "$2a$04$8ev1j...f6ICL.ezS....", reset_password_sent_at: nil, default_language: nil, uid: nil, api_key: "rmhh...noyn">]>
[144004]
[]
The strange thing is. I have user with id. map
can get them. pluck
not.
I don't understand sql log also. How can I get map id
result without any select in sql log? Caching ?
pluck
doesnt work on an array, it works on anActiveRecord::Relation
, it's goal is to avoid to make a full query to only get the ids.Once you've retrieved all columns from db, you can just
map
what you need.You create the array when you do
self.users -= users_to_remove
, or maybe even when you do.present?
, since you should use.exists?
This line:
Doesn't fire off SQL query immediately. It sends the request whenever you need some details of these users. And it caches the result in SQL cache (so when the same request goes to DB again, it intercepted by Rails and never reaches the database).
So when you call:
It uses that cached result. But when you use
It re-fetches the result, because the actual SQL query differs. With
#map
it isSELECT * FROM ...
, and with#pluck
it'sSELECT id FROM...
. And when query reaches the database, IDs doesn't belong to 'self' any longer (you deleted them right before that), so they aren't returned.