Rails 4 ИЛИ запрос с таблицей соединений, используя группу и имея

У меня есть запрос Rails 4, подобный этому:

user.positions.where('positions.active = ? OR positions.deadline < ?', false, Date.current).joins(:cvs).where(cvs: {accepted: true}).group(:id).having('COUNT(cvs.id) = 3')

Теперь это производит следующий SQL-запрос:

SELECT `positions`.* FROM `positions` INNER JOIN `cvs` ON `cvs`.`position_id` = `positions`.`id` WHERE `positions`.`user_id` = 4 AND (positions.active = 0 OR positions.deadline < '2015-01-21') AND `cvs`.`accepted` = 1 GROUP BY id HAVING COUNT(cvs.id) = 3

Что мне действительно нужно, так это сделать второй запрос where с условием OR, но запрос сверху приводит к условию AND.

Я также пробовал следующее:

user.positions.joins(:cvs).where('positions.active = ? OR positions.deadline < ? OR cvs.accepted = 1 GROUP BY id HAVING COUNT(cvs.id) = ?', false, Date.current, 3)

но это преобразуется Rails в

SELECT  `positions`.* FROM `positions` INNER JOIN `cvs` ON `cvs`.`position_id` = `positions`.`id` WHERE `positions`.`user_id` = 4 AND (positions.active = 0 OR positions.deadline < '2015-01-21' OR cvs.accepted = 1 GROUP BY id HAVING COUNT(cvs.id) = 3)

который выдает синтаксическую ошибку sql из-за закрывающей скобки в конце. Без открывающей и закрывающей скобки или если поставить закрывающую скобку после «2015-01-21», это сработает. Но я не знаю, как сказать Rails не ставить здесь никаких скобок.

(Что я действительно хочу запросить, так это все позиции, которые не активны ИЛИ те, где крайний срок уже истек ИЛИ где позиция имеет 3 принятых резюме)


person user4479145    schedule 21.01.2015    source источник


Ответы (1)


ActiveRecord не может сделать or, но Arel может. Удивительный scuttle.io решит вашу проблему:

Position.select(Position.arel_table[Arel.star]).where(
  Position.arel_table[:user_id].eq(4).or(
    Position.arel_table[:active].eq(0).or(Position.arel_table[:deadline].lt('2015-01-21')).or(Cv.arel_table[:accepted].eq(1))
  )
).joins(
  Position.arel_table.join(Cv.arel_table).on(
    Cv.arel_table[:position_id].eq(Position.arel_table[:id])
  ).join_sources
).group(:id)
person Dan Kohn    schedule 21.01.2015
comment
Спасибо за предложение. scuttle.io кажется классным инструментом, но генерируемый им запрос не учитывает «имеющий счет (cvs.id) = 3». Кроме того, Position.arel_table[:user_id].eq(4) на самом деле не работает, так как запрос также возвращает позиции других пользователей. - person user4479145; 21.01.2015
comment
Вот синтаксис для having. github.com/rails/arel#more-sophisticated-queries Я бы посоветовал регистрация ошибки с автором scuttle, поскольку он был очень отзывчивым. - person Dan Kohn; 22.01.2015