ruby-on-rails - through - rails sql query
Rails 4 alcance para encontrar padres sin hijos (3)
@MrYoshiji tiene una sólida respuesta de Rails 4, pero para la gente que viene con Rails 5, tienes más opciones.
Usando Rails 5:
A partir de Rails 5, también puedes usar left_outer_joins para evitar cargar la asociación. Fue introducido en la solicitud de extracción #12071 .
scope :without_children, left_outer_joins(:children).where(children: { id: nil })
Para padres con hijos, la solución de MrYoshiji''s Rails 4 sigue siendo la que se debe usar:
scope :with_children, joins(:children)
Encontré una answer que tenía algunos ejemplos utilizables para encontrar padres con n
hijos, pero la misma no se puede utilizar para encontrar padres sin hijos (presumiblemente porque la unión los excluye).
scope :with_children, joins(:children).group("child_join_table.parent_id").having("count(child_join_table.parent_id) > 0")
¿Alguien puede señalarme en la dirección correcta?
Así es como lo resolví para Rails 5:
scope :without_comments, -> do
left_outer_joins(:comments).where(comments: { id: nil })
end
Esto debería hacer el trabajo que desea:
Carriles 3 y 4
scope :without_children, includes(:children).where(:children => { :id => nil })
La gran diferencia aquí es que las joins
convierten en includes
: un incluir carga todas las relaciones, si existen, la unión solo cargará los objetos asociados e ignorará el objeto sin una relación.
De hecho, el scope :with_children, joins(:children)
debería ser suficiente para devolver Parent con al menos 1 hijo. ¡Pruébalo!
Carriles 5
Ver la respuesta de @ Anson a continuación
Como señaló @MauroDias, si se trata de una relación autorreferencial entre sus padres e hijos, este código anterior no funcionará.
Con un poco de investigación, descubrí cómo hacerlo:
Considera este modelo:
class Item < ActiveRecord::Base
has_many :children, :class_name => ''Item'', :foreign_key => ''parent_id''
Cómo devolver todos los artículos sin ningún niño (s):
Item.includes(:children).where(children_items: { id: nil })
¿Cómo encontré esa tabla children_items
?
Item.joins(:children)
genera el siguiente SQL:
SELECT "items".*
FROM "items"
INNER JOIN "items" "children_items"
ON "children_items"."parent_id" = "items"."id"
Así que supuse que Rails usa una tabla cuando necesita un JOIN en un caso autorreferencial.
Preguntas similares: