Reputation: 2508
I know these two statements perform the same SQL:
Using select
User.select(:email)
# SELECT `users`.`email` FROM `users`
And using pluck
User.all.pluck(:email)
# SELECT `users`.`email` FROM `users`
Now I need to get the SQL statement derived from each method. Given that the select
method returns an ActiveRecord::Relation
, I can call the to_sql
method. However, I cannot figure out how to get the SQL statement derived from a pluck operation on an ActiveRecord::Relation
object, given that the result is an array.
Please, take into account that this is a simplification of the problem. The number of attributes plucked can be arbitrarily high.
Any help would be appreciated.
Upvotes: 12
Views: 4877
Reputation: 33542
You cannot chain to_sql
with pluck
as it doesn't return ActiveRecord::relation
. If you try to do, it throws an exception like so
NoMethodError: undefined method `to_sql' for [[""]]:Array
I cannot figure out how to get the SQL statement derived from a pluck operation on an ActiveRecord::Relation object, given that the result is an array.
Well, as @cschroed pointed out in the comments, they both(select
and pluck
) perform same SQL queries. The only difference is that pluck
return an array
instead of ActiveRecord::Relation
. It doesn't matter how many attributes you are trying to pluck, the SQL statement will be same as select
Example:
User.select(:first_name,:email)
#=> SELECT "users"."first_name", "users"."email" FROM "users"
Same for pluck
too
User.all.pluck(:first_name,:email)
#=> SELECT "users"."first_name", "users"."email" FROM "users"
So, you just need to take the SQL statement returned by the select
and believe that it is the same for the pluck
. That's it!
Upvotes: 11
Reputation: 1058
You could monkey-patch the ActiveRecord::LogSubscriber
class and provide a singleton that would register any active record queries, even the ones that doesn't return ActiveRecord::Relation
objects:
class QueriesRegister
include Singleton
def queries
@queries ||= []
end
def flush
@queries = []
end
end
module ActiveRecord
class LogSubscriber < ActiveSupport::LogSubscriber
def sql(event)
QueriesRegister.instance.queries << event.payload[:sql]
"#{event.payload[:name]} (#{event.duration}) #{event.payload[:sql]}"
end
end
end
Run you query:
User.all.pluck(:email)
Then, to retrieve the queries:
QueriesRegister.instance.queries
Upvotes: 3