2017-01-08 2 views
1

У меня есть таблица ресторанов, в которых есть много оговорок. Теперь я хотел бы запросить все рестораны, и в случае, если у них есть резервация на 2 человека, он должен предварительно загрузить эти ассоциации. Если нет резерваций на 2, он все равно должен возвращать рестораны, но с пустой ассоциацией.Eager-load для пользовательских подключений в ActiveRecord

Для этого я попробовал следующий запрос:

Restaurant.eager_load(:reservations).where("number_of_people = ?", 2) 

Однако, это не работает, так как он отбрасывает все рестораны, которые делают есть оговорки, но ни один из них не является для 2-х человек.

Итак, что бы я хотел сделать, это переместить это условие в условие соединения. Что-то вроде:

Restaurant.joins('LEFT OUTER JOIN \"reservations\" ON \"reservations\".\"restaurant_id\" = \"restaurants\".\"id\" AND \"reservations\".\"number_of_people\" = ?', 2) 

Это дало бы результат мне нужно, однако это не поджимать «оговорки» ассоциаций, но вызывает вопрос N + 1.

Не похоже, что eager_load принимает пользовательские запросы. Я нашел эти темы: https://github.com/rails/rails/issues/12270 и JOIN ON ... AND conditions when eager loading association in ActiveRecord, но решения не найдено.

+0

вы можете использовать '' includes' вместо joins' – uzaif

+0

'includes' Безразлично» t принять пользовательский SQL либо –

+0

Вам нужно создать новую задницу ociation с условием –

ответ

1

Я думаю, что Дипак прав. Попробуйте это:

#retaurant.rb 
has_many :reservations_for_two, ->{number_of_people: 2}, class_name: 'Reservation' 

А потом:

Restaurant.preload(:reservations_for_two) #(for two separate queries) 

ИЛИ

Restaurant.eager_load(:reservations_for_two) #(one join query) 
+0

Мне нужно, чтобы это было динамическим, хотя я могу указать 'number_of_people' в качестве аргумента вместо hardcoding. –

0

Попробуйте Restaurant.joins(:reservations).includes(:reservations).where("reservations.number_of_people = ?", 2)

+0

Это также создает оператор« WHERE »и не помещает его в« ON », состояние. –

+1

Хорошо, у меня есть ваш вопрос. Второй ответ прав, поскольку из-за жесткого кодирования значение одного грязного взлома заключается в создании класса {number_of_people: Restaurant.number_of_people_to_query} , class_name: «Резервация», и до начала загрузки назначьте свои критерии атрибуту класса. – ClassyPimp

+0

Это работает, но только в однопоточной среде. Меня беспокоят условия гонки, учитывая, что в ней используется переменная класса. –

Смежные вопросы