Подтвердить что ты не робот

Rails 4 позволяет найти родителей без детей

Я нашел один ответ, в котором были некоторые примеры использования having для поиска родителей с детьми n, но то же самое нельзя использовать для поиска родителей без детей (предположительно, поскольку объединение исключает их).

scope :with_children, joins(:children).group("child_join_table.parent_id").having("count(child_join_table.parent_id) > 0")

Может ли кто-нибудь указать мне в правильном направлении?

4b9b3361

Ответ 1

Это должно выполнить нужную работу:

Рельсы 3 и 4

scope :without_children, includes(:children).where(:children => { :id => nil })

Большая разница здесь в том, что joins становится includes: a include загружает все отношения, если они существуют, соединение будет загружать только связанные объекты и игнорировать объект без отношения.

На самом деле, scope :with_children, joins(:children) должно быть достаточно, чтобы вернуть родителя с по крайней мере 1 ребенком. Попробуйте!

Рельсы 5

См. ниже ответ @Anson


Как отметил @MauroDias, , если это соотношение между репликами между вашим родителем и дочерними элементами, этот код выше не будет работать.

С небольшим количеством исследований я узнал, как это сделать:

Рассмотрим эту модель:

class Item < ActiveRecord::Base
  has_many :children, :class_name => 'Item', :foreign_key => 'parent_id'

Как вернуть все элементы без child (ren):

Item.includes(:children).where(children_items: { id: nil })

Как я нашел таблицу children_items?

Item.joins(:children) генерирует следующий SQL:

SELECT "items".* 
FROM "items" 
 INNER JOIN "items" "children_items" 
 ON "children_items"."parent_id" = "items"."id"

Итак, я догадался, что Rails использует таблицу, когда нуждается в JOIN в самореферентном случае.


Похожие вопросы:

Ответ 2

@MrYoshiji имеет надежный ответ Rails 4, но для людей, приезжающих сюда с Rails 5, у вас есть больше вариантов.

Использование Rails 5:

В Rails 5 вы также можете использовать left_outer_joins, чтобы избежать загрузки ассоциации. Он был введен в запрос тяги # 12071.

scope :without_children, left_outer_joins(:children).where(children: { id: nil })

Для родителей с детьми решение MrYoshiji Rails 4 по-прежнему используется:

scope :with_children, joins(:children)