ActiveRecord #include, с условием, но загружает все отношения, а не только те, которые соответствуют условию - PullRequest
3 голосов
/ 14 февраля 2020

У меня есть модели ActiveRecord Parent и Kid. У родителей много детей.

У меня есть родитель, которого зовут папа, с тремя детьми, которых зовут Авель, Бобби и Каин. Я хочу найти Родителя на основе имени только одного из Детей.

parent = Parent.includes(:kids).
  find_by(kids: { name: 'Bobby' })

Приведенный выше запрос предоставляет мне нужного Родителя, но parent.kids включает только Бобби. Я хочу, чтобы Авель и Каин были также включены в parent.kids, как если бы я это сделал:

Parent.find_by(name: 'Dad').kids

Я мог бы сделать:

Parent.includes(:kids).
  find_by(kids: { name: 'Bobby' }).
  tap { |parent| parent&.kids.reload }

Но разве нет «лучше «Как выбрать остальных детей? Например, есть ли способ, которым я мог бы загрузить все дочерние элементы родительского элемента при запросе родительского элемента (с помощью одного оператора SQL)?

Ответы [ 2 ]

2 голосов
/ 14 февраля 2020

Вы хотите INNER JOIN:

parents = Parent.joins(:kids).where(kids: { name: 'Bobby' })

Это будет включать только строки от родителей с совпадением в таблице детей. Вы можете применить его как подзапрос, чтобы избежать удаления оставшихся соединенных строк:

parents = Parent.where(
            id: Parent.joins(:kids).where(kids: { name: 'Bobby' })
          ).includes(:kids)
2 голосов
/ 14 февраля 2020

Как насчет создания Parent.includes(:kids).find_by(kids: { name: 'Bobby' } подзапроса

Parent.includes(:kids).where(id: Parent.includes(:kids).find_by(kids: { name: 'Bobby' })
...