ActiveRecordy has_many через Мне нужно найти всех родителей, у которых хотя бы один ребенок соответствует условию - PullRequest
0 голосов
/ 03 августа 2020

У меня есть три модели activerecord:

«A»

class User < ApplicationRecord
  has_many :user_violation, class_name: "UserViolation", inverse_of: :user
  has_many :violations, through: :user_violation, class_name: "Violation"
end

средний:

class UserViolation < ApplicationRecord
  belongs_to :user, class_name: "User", foreign_key: :user_id
  belongs_to :violation, class_name: "Violation", foreign_key: :violation_id
end

B:

class Violation < ApplicationRecord
end

Мне нужно найти всех пользователей, у которых есть МИНИМУМ одно нарушение со столбцом: fatal установлено значение true.

Я как бы застрял здесь, и это не работает:

User.joins(:violations).where('violations.fatal = true')

Ответы [ 3 ]

3 голосов
/ 03 августа 2020

Чтобы использовать условие фильтра запроса в ORM, я думаю, этот синтаксис должен быть:

User.joins(:violations).where(violations: {fatal: 'true'})
1 голос
/ 03 августа 2020

Я думаю, что ответ @Ninh Le правильный, (как и ваш!), Возможно, вы можете сначала упростить код своих моделей, чтобы попытаться найти, в чем проблема. Например, я заметил, что вы пропустили 's' в отношении has_many:

class User < ApplicationRecord
  has_many :user_violations
  has_many :violations, through: :user_violations
end

class UserViolation < ApplicationRecord
  belongs_to :user
  belongs_to :violation
end

class Violation < ApplicationRecord
  # has_many :user_violations
  # has_many :violations, through: :user_violations
end

Я думаю, это должно сработать, если это все еще не так, проверьте, есть ли запись, у которой есть нарушение .fatal == true.

Затем добавьте параметры has_many, own_to, если это действительно необходимо.

0 голосов
/ 15 августа 2020

Для наиболее эффективного подхода к поиску этих пользователей вам понадобится то, что люди, работающие с базой данных, назвали бы «полусоединением» - существующим подзапросом.

Предполагая, что «фатальный "определяется столбцом fatal, имеющим значение true

User.
  where(
  Violation.
    where(fatal: true).
    joins(:user_violations).
    where(
      UserViolation.arel_table[:user_id].eq(User.arel_table[:id])
    ).arel.exists
  )

. Я бы предложил добавить в Violation область, определяющую fatal, без необходимости использования в этом предложении where.

...