update through rails query left includes has_one has_and_belongs_to_many ruby-on-rails activerecord

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: