2013-02-22 8 views
5

Mam ten przypadek użycia, gdy otrzymuję symbolizowane głębokie skojarzenia z określonego modelu i muszę wykonać pewne zapytania, które wymagają użycia zewnętrznych sprzężeń. Jak można to zrobić BEZ uciekania się do pisania pełnego SQL ręcznie?Arel: Lewe sprzężenie zewnętrzne za pomocą symboli

Odpowiedzi Nie chcę: - używanie zawiera (nie rozwiązuje głębokich skojarzeń bardzo dobrze (.includes (: cars => [: windows,: engine => [: ignition] ..... works nieoczekiwanie) i nie chcę jego efektów ubocznych) - pisanie samego SQL'a (przepraszam, to 2013, obsługa wielu db, etc etc ..., a obiekty, które pobieram są read_only, więcej efektów ubocznych)

Chciałbym mieć rozwiązanie Arel Wiem, że używając arel_table z modeli mogę konstruować wyrażenia SQL, istnieje również DSL dla złączeń, ale jakoś nie mogę go używać w metodzie łączenia z modelu:

car = Car.arel_table 
engine = Engine.arel_table 

eng_exp = car.join(engine).on(car[:engine_id].eq(engine[:id])) 
eng_exp.to_sql #=> GOOD! very nice! 
Car.joins(eng_exp) #=> Breaks!! 

Dlaczego to nie działa, jest poza mną. Nie wiem dokładnie, czego brakuje. Ale jest to najbliższe rozwiązanie, które mam teraz. Jeśli ktoś mógłby mi pomóc w wypełnieniu mojego przykładu lub zapewnić mi dobrą pracę dookoła lub powiedzieć mi, kiedy Railsy będą zawierały taką oczywistą niezbędną funkcję, będę miał moją wieczną wdzięczność.

Odpowiedz

6

znalazłam na blogu, który może służyć do rozwiązania tego problemu: http://blog.donwilson.net/2011/11/constructing-a-less-than-simple-query-with-rails-and-arel/

opiera się na tym (i moje własne badania) dodaje powinny działać w danej sytuacji:

car = Car.arel_table 
engine = Engine.arel_table 

sql = car.project(car[Arel.star]) 
     .join(engine, Arel::Nodes::OuterJoin).on(car[:engine_id].eq(engine[:id])) 

Car.find_by_sql(sql) 
+0

dobrze, to jest najbliżej odpowiedzi będziemy kiedykolwiek, jestem boję się, mój jedyny problem z byciem wcześniejszą znajomością kluczy asocjacyjnych (chciałbym mieć bardziej nieszablonowe rozwiązanie na ten temat, jak zwykłe regularne sprzężenia AR). Ale to zdecydowanie najlepsza odpowiedź na to pytanie, ja już wymyśliłem rozwiązanie oparte na nim. Jeszcze raz. – ChuckE

6

To jest stara pytanie, ale z korzyścią dla każdego, znalezienie go przez wyszukiwarki:

Jeśli chcesz coś można przekazać do .joins, można użyć .create_join i .create_on:

join_on = car.create_on(car[:engine_id].eq(engine[:id])) 
eng_join = car.create_join(engine, join_on, Arel::Nodes::OuterJoin) 

Car.joins(eng_join) 

LUB

użyć .join_sources z wybudowanym przyłączenia obiektu:

eng_exp = car.join(engine, Arel::Nodes::OuterJoin).on(car[:engine_id].eq(engine[:id])) 
Car.joins(eng_exp.join_sources) 
0

Jeśli nie przeszkadza dodając zależność i omijając AREL ogóle można użyć Ernie Miller's excellent Squeel gem. Byłoby coś

Car.joins{engine.outer}.where(...) 

Wymagałoby to, że model samochodu wiązać się z silnika tak:

belongs_to :engine 
Powiązane problemy