2017-08-28 47 views
9

Znam te dwa stwierdzenia wykonać tę samą SQL:ActiveRecord zrywać do SQL

Korzystanie select

User.select(:email) 
# SELECT `users`.`email` FROM `users` 

i korzystania pluck

User.all.pluck(:email) 
# SELECT `users`.`email` FROM `users` 

Teraz muszę uzyskać SQL pochodzący z każda metoda. Biorąc pod uwagę, że metoda select zwraca wartość ActiveRecord::Relation, mogę wywołać metodę to_sql. Jednak nie mogę dowiedzieć się, jak uzyskać instrukcję SQL wyprowadzoną z operacji pluck na obiekcie ActiveRecord::Relation, biorąc pod uwagę, że wynikiem jest tablica.

Proszę wziąć pod uwagę, że jest to uproszczenie problemu. Liczba wyskubanych atrybutów może być dowolnie wysoka.

Każda pomoc zostanie doceniona.

+2

Co tryi do zrobienia? ['pluck'] (https://github.com/rails/rails/blob/master/activerecord/lib/active_record/relation/calculations.rb#L177) używa tego samego zapytania SQL co' select', ale używa [' cast_values'] (https://github.com/rails/rails/blob/master/activerecord/lib/active_record/result.rb#L99), aby zwrócić tablicę zamiast "ActiveRecord :: Relation". – cschroed

+0

Buduję zapytanie na podstawie danych wprowadzanych przez użytkownika i chcę przekazać opinię na temat zapytania, które faktycznie jest wykonywane. – Bustikiller

Odpowiedz

8

Ty nie łańcuch to_sql z pluck gdyż nie zwracaActiveRecord::relation. Jeśli próbujesz zrobić, to zgłasza wyjątek, podobnie jak

NoMethodError: undefined method `to_sql' for [[""]]:Array 

nie mogę dowiedzieć się, jak uzyskać SQL pochodzący z oskubać operacji na obiekcie ActiveRecord :: Relation, zważywszy, że w wyniku jest tablicą.

Cóż, jak @cschroed zauważył w komentarzach, oboje (select i pluck) wykonywać samo zapytań SQL. Jedyna różnica polega na tym, że pluck zwraca array zamiast ActiveRecord::Relation. To nie ma znaczenia jak wiele atrybuty próbują oskubać, SQL będzie taka sama jak select

Przykład:

User.select(:first_name,:email) 
#=> SELECT "users"."first_name", "users"."email" FROM "users" 

samo dla pluck zbyt

User.all.pluck(:first_name,:email) 
#=> SELECT "users"."first_name", "users"."email" FROM "users" 

Musisz więc wziąć instrukcję SQL zwróconą przez select i uważać, że jest ona taka sama dla pluck. To jest to!

2

Mogłeś monkey-patch klasę ActiveRecord::LogSubscriber i zapewniają, że pojedyncza rejestracji aktywnych zapytań rekordowe, nawet te, które nie zwraca ActiveRecord::Relation obiekty:

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 kwerendy:

User.all.pluck(:email) 

Następnie, aby odzyskać zapytania:

QueriesRegister.instance.queries 
+0

Kiedy zostanie opróżniona tablica 'zapytań'? – Bustikiller

+0

Cóż ... Trzeba to kontrolować samodzielnie za pomocą metody "# flush" –