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.
2 Answers
Answers 1
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!
Answers 2
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
0 comments:
Post a Comment