Използване на arel
може да те отведе доста далеч. Сложната част е как да не напишете цялата си заявка с arel
собствен синтаксис на заявката?
Ето един трик:когато създавате вашата заявка, като използвате where
, ако използвате arel
условия, получавате някои допълнителни методи безплатно. Например, можете да опашкате подзаявката, която имате там, с .exists.not
, което ще ви даде (NOT ( EXISTS (subquery)))
Хвърлете това в where
на родителя -клауза и сте готови.
Въпросът е как препращате към включените таблици? Имаш нужда от Арел за това. Вие можете използвайте where
на Arel със своите грозни условия като a.eq b
. Но защо? Тъй като това е условие за равенство, можете да използвате условията на Rails вместо това! Можете да посочите таблицата, която заявявате, с ключ за хеширане, но за другата таблица (във външната заявка) можете да използвате нейния arel_table
. Гледайте това:
parents = Parent.arel_table
Parent.where(
Child.where(other_parent_id: nil, parent_id: parents[:id]).exists.not
)
Можете дори да намалите използването на Arel, като прибягвате малко до низове и разчитате на факта, че можете да подавате подзаявки като параметри към where
на Rails . Няма много полза от него, но не ви принуждава да се задълбочавате твърде много в методите на Arel, така че можете да използвате този трик или други SQL оператори, които приемат подзаявка (има ли други?):
parents = Parent.arel_table
Parent.where('NOT EXISTS (?)',
Child.where(parent_id: parents[:id], other_parent_id: nil)
)
Двете основни точки тук са:
- Можете да създавате подзаявки точно по същия начин, по който сте свикнали да създавате обикновени заявки, препращайки към таблицата на външната заявка с Arel. Може дори да не е истинска маса, може да е псевдоним! Луди неща.
- Можете да използвате подзаявки като параметри за
where
на Rails методът е много добър.