2013-02-22 3 views
5

У меня есть этот прецедент, где я получаю символизированные глубокие ассоциации от определенной модели, и мне приходится выполнять определенные запросы, которые связаны с использованием внешних соединений. Как это сделать, не прибегая к написанию полного SQL вручную?Arel: Левое внешнее соединение с использованием символов

Ответы, которые я не хочу: - Использование включает (не разрешает глубокие ассоциации очень хорошо (.includes (: cars => [: windows,: engine => [: ignition] ..... works неожиданно), и я не хочу его побочных эффектов) - писать SQL сам (извините, это 2013 год, поддержка кросс-db и т. д. и т. д.), а объекты, которые я получаю, являются read_only, больше побочных эффектов)

Я хотел бы иметь решение Arel. Я знаю, что с использованием isl_table из моделей я могу создавать выражения SQL, есть также DSL для соединений, но почему-то я не могу использовать его в методе joins из модели:

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!! 

Почему это не работает вне меня. Я точно не знаю, чего не хватает. Но это самое близкое к решению, которое у меня есть сейчас. Если кто-то может помочь мне заполнить мой пример или дать мне приятный обход или сказать мне, когда Rails включит такую ​​явно необходимую функцию, я буду иметь свою вечную благодарность.

ответ

6

Я нашел в блоге, что претендует на решение этой проблемы: http://blog.donwilson.net/2011/11/constructing-a-less-than-simple-query-with-rails-and-arel/

Основываясь на этом (и мое собственное тестирование), должны работать для вашей ситуации:

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

Ну, это ближе всего к ответу, мы когда-нибудь, я боюсь, моя единственная проблема - быть предыдущим знанием ключей ассоциации (я хотел бы иметь более готовое решение по этому поводу, например, обычные обычные внутренние AR-соединения). Но это, безусловно, лучший ответ на этот вопрос, я уже разработал решение, основанное на нем. Thx снова. – ChuckE

6

Это старое вопрос, но в пользу кого-либо найти его с помощью поисковых систем:

Если вы хотите что-то вы можете перейти в .joins, вы можете использовать либо .create_join и .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) 

ИЛИ

.join_sources использовать из вашего построенного объекта присоединиться:

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

Если вы не возражаете, добавив зависимость и вообще пропуская AREL, вы могли бы использовать Ernie Miller's excellent Squeel gem. Было бы что-то вроде

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

Это потребовало бы, что модель автомобиля ассоциироваться с двигателя следующим образом:

belongs_to :engine 
Смежные вопросы