2013-07-02 5 views
9

Usiłuję zbudować kwerendę w następujący sposób:Budowanie relacji ActiveRecord bez konieczności to wykonać zapytanie

rel = article.where(version: 'some_version') 
      .joins(:categories) 
      .merge(Category.where(:uuid => 'some_cat_uuid')) 

articles = rel.where(published: true).limit(10) 
# etc. 

Problemem jest to pierwsze zapytanie wydaje się wykonać bez względu na to, co robię. czy robię coś źle?

+0

Umm, jesteś druga zmienna 'articles' wykorzystuje swoją pierwszą zmienną' rel'. Oczywiście za każdym razem wykona to zapytanie! –

+2

@ n_i_c_k jak to zrobić? Możesz łączyć zapytania typu "arel" w ten sposób. Podejrzewam, że wykonanie zapytania dzieje się z powodu, że '.merge' ... – nzifnab

+3

Scratch, że' .merge' nie powinny wykonywać kwerendy. Czy robisz to w konsoli? – nzifnab

Odpowiedz

13

Po uruchomieniu polecenia w konsoli, to automatycznie dodaje coś podobnego do .inspect w końcu do wyświetlania wyników polecenia. Na przykład (jest to w moim app, że pracuję na teraz):

irb(main):061:0> Job.where(id: 251000) 
    Job Load (3.8ms) SELECT "jobs".* FROM "jobs" WHERE "jobs"."deleted_at" IS NULL AND "jobs"."id" = 251000 
=> [#<Job id: 251000, {...}>] 

Tak, to pierwsza linia kodu jest po prostu w porządku, a nie normalnie wykonać zapytanie, ale skoro zostały uruchomione go w konsola, którą uruchamia natychmiast, aby mogła wyświetlić wyniki dla ciebie.

Jednym ze sposobów obejścia tego jest dodanie do końca polecenia ; nil, w ten sposób konsola nie będzie próbować wyświetlać wyników (po prostu wyświetli zero jako wynik tej linii. IE:

irb(main):062:0> Job.where(id: 251000); nil 
=> nil 

Robi to w ten sposób, powinieneś być w stanie zrobić to, czego się spodziewaliśmy (wykonanie opóźnienia zapytania aż rzeczywiście potrzebne wyniki):

rel = article.where(version: 'some_version') 
      .joins(:categories) 
      .merge(Category.where(:uuid => 'some_cat_uuid')); nil 

articles = rel.where(published: true).limit(10); nil 

Następnie można wykonać kwerendy przy użyciu articles.all (w Rails 3) lub articles.to_a (w Rails 4)

Oczywiście, jeśli następnie przeniesiesz ten kod do zadania lub modelu prowizji lub coś, co można upuścić te bity ; nil, ponieważ wyglądają trochę zagracone i będą bezużyteczne w tym momencie.

Kolejnym punktem spornym dla konsoli może być tak, że będzie to widać, że .where() {NEWLINE} i wykonanie zapytania w tym punkcie, staram się postawić kropkę na poprzedniej kolejce, aby usunąć wszelkie niejasności, gdzie kończy się moje polecenie:

rel = article.where(version: 'some_version'). 
      joins(:categories). 
      merge(Category.where(:uuid => 'some_cat_uuid')); nil 
+0

Idealny. Dzięki – rainkinz

+3

Wygląda na to, że działa to tylko z [ActiveRecord :: QueryMethods] (http://api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html) ('where',' join', 'group', itp.) . To NIE działa z [ActiveRecord :: FinderMethods] (http://api.rubyonrails.org/classes/ActiveRecord/FinderMethods.html) ('first',' find', 'find_by', itp.). 'FinderMethods' natychmiast wykona zapytanie niezależnie od'; składnia zerowa. – jhirsch

+1

@Crazydog tak, ale to dlatego, że nie są to metody obciążone ładowaniem. Te metody wczytują się natychmiast, bez względu na to, skąd pochodzą. – nzifnab