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
whereRails můžete použít poddotazy metoda je v pořádku.