Pomocí arel
může vás dostat docela daleko. Záludná část je, jak nenapíšete celý dotaz pomocí arel
vlastní syntaxi dotazu?
Zde je trik:při vytváření dotazu pomocí where
, pokud používáte arel
podmínky, získáte některé metody navíc zdarma. Například poddotaz, který tam máte, můžete omezit pomocí .exists.not
, čímž získáte (NOT ( EXISTS (subquery)))
Hoďte to do where
rodiče -klauzule a máte hotovo.
Otázkou je, jak odkazujete na příslušné tabulky? K tomu potřebujete Arela. Mohli byste použijte Arelovo where
s jeho ošklivými podmínkami jako a.eq b
. Ale proč? Protože se jedná o podmínku rovnosti, můžete místo toho použít podmínky Rails! Na tabulku, na kterou se dotazujete, můžete odkazovat pomocí hash klíče, ale pro druhou tabulku (ve vnějším dotazu) můžete použít její arel_table
. Podívejte se na toto:
parents = Parent.arel_table
Parent.where(
Child.where(other_parent_id: nil, parent_id: parents[:id]).exists.not
)
Využití Arelu můžete dokonce snížit tím, že se trochu uchýlíte k řetězcům a spolehnete se na skutečnost, že můžete vkládat dílčí dotazy jako parametry do where
Rails . Není to moc užitečné, ale nenutí vás to příliš vrtat v Arelových metodách, takže můžete použít ten trik nebo jiné SQL operátory, které převezmou poddotaz (existují ještě nějaké další?):
parents = Parent.arel_table
Parent.where('NOT EXISTS (?)',
Child.where(parent_id: parents[:id], other_parent_id: nil)
)
Zde jsou dva hlavní body:
- Můžete vytvářet poddotazy stejným způsobem, jakým jste zvyklí vytvářet běžné dotazy, odkazováním na tabulku vnějšího dotazu s Arel. Nemusí to být ani skutečný stůl, může to být alias! Bláznivé věci.
- Jako parametry pro
where
Rails můžete použít poddotazy metoda je v pořádku.