Gebruik arel
kan je behoorlijk ver brengen. Het lastige is hoe je niet je hele zoekopdracht schrijft met arel
's eigen query-syntaxis?
Hier is een truc:bij het maken van uw zoekopdracht met where
, als je arel
. gebruikt voorwaarden, krijg je een aantal extra methoden gratis. U kunt bijvoorbeeld de subquery die u daar heeft volgen met .exists.not
, waarmee u een (NOT ( EXISTS (subquery)))
Gooi dat in where
van de ouders -clausule en je bent klaar.
De vraag is, hoe verwijs je naar de betrokken tabellen? Daar heb je Arel voor nodig. Je zou gebruik Arel's where
met zijn lelijke voorwaarden zoals a.eq b
. Maar waarom? Omdat het een gelijkheidsvoorwaarde is, kunt u in plaats daarvan de voorwaarden van Rails gebruiken! U kunt verwijzen naar de tabel die u opvraagt met een hash-sleutel, maar voor de andere tabel (in de buitenste query) kunt u de arel_table
gebruiken . Bekijk dit:
parents = Parent.arel_table
Parent.where(
Child.where(other_parent_id: nil, parent_id: parents[:id]).exists.not
)
Je kunt het Arel-gebruik zelfs verminderen door een beetje gebruik te maken van strings en te vertrouwen op het feit dat je subquery's als parameters kunt invoeren in Rails' where
. Het heeft niet veel nut, maar het dwingt je niet om te veel in Arel's methoden te graven, dus je kunt die truc of andere SQL-operators gebruiken die een subquery nemen (zijn er zelfs andere?):
parents = Parent.arel_table
Parent.where('NOT EXISTS (?)',
Child.where(parent_id: parents[:id], other_parent_id: nil)
)
De twee belangrijkste punten hier zijn:
- U kunt subquery's maken op dezelfde manier als u gewend bent om gewone query's te maken, verwijzend naar de tabel van de buitenste query met Arel. Het is misschien niet eens een echte tafel, het kan een alias zijn! Gekke dingen.
- U kunt subquery's gebruiken als parameters voor
where
. van Rails methode prima.