Usando arel
puede llevarte bastante lejos. La parte complicada es cómo no escribes tu consulta completa usando arel
¿La sintaxis de consulta propia?
Aquí hay un truco:al construir su consulta usando where
, si usa arel
condiciones, obtienes algunos métodos adicionales gratis. Por ejemplo, puede seguir la subconsulta que tiene allí con .exists.not
, que le dará un (NOT ( EXISTS (subquery)))
Tira eso en el where
de los padres -cláusula y listo.
La pregunta es, ¿cómo hace referencia a las tablas involucradas? Necesitas a Arel para eso. podrías usa el where
de Arel con sus feas condiciones como a.eq b
. ¿Pero por qué? Como es una condición de igualdad, ¡puedes usar las condiciones de Rails en su lugar! Puede hacer referencia a la tabla que está consultando con una clave hash, pero para la otra tabla (en la consulta externa) puede usar su arel_table
. Mira esto:
parents = Parent.arel_table
Parent.where(
Child.where(other_parent_id: nil, parent_id: parents[:id]).exists.not
)
Incluso puede reducir el uso de Arel recurriendo un poco a cadenas y confiando en el hecho de que puede alimentar subconsultas como parámetros al where
de Rails . No sirve de mucho, pero no te obliga a profundizar demasiado en los métodos de Arel, por lo que puedes usar ese truco u otros operadores SQL que toman una subconsulta (¿hay incluso otros?):
parents = Parent.arel_table
Parent.where('NOT EXISTS (?)',
Child.where(parent_id: parents[:id], other_parent_id: nil)
)
Los dos puntos principales aquí son:
- Puede crear subconsultas de la misma forma en que está acostumbrado a crear consultas regulares, haciendo referencia a la tabla de consultas externas con Arel. Puede que ni siquiera sea una tabla real, ¡puede que sea un alias! Cosas locas.
- Puede usar subconsultas como parámetros para el
where
de Rails método muy bien.