Существует модель проекта и модель оплаты:
class Project < ApplicationRecord
has_many :payments
end
class Payment < ApplicationRecord
belongs_to :project
end
Мне довольно легко комбинировать запросы для столбцов с or
ИЛИ and
.
Project.where(projects[:created_at].gt(6.months.ago).or(projects[:updated_at].gt(1.month.ago)))
Причина использования Arel заключается в том, что точные столбцы, операторы и значения исходят от пользователя, и операторы Arel очень хорошо соответствуют тому, что пользователь может выбрать.
Однако, если я хочу объединить это с данными из другого связанную таблицу, то я просто не могу понять, что делать. ActiverRecord требует OR
для структурной совместимости, поэтому я не могу сделать:
Project.where(projects[:created_at].gt(6.months.ago)).or(Project.joins(:payments))
Что-то вроде этого: Project.where(projects[:created_at].gt(6.months.ago).or(projects.join(payments).on(projects[:id].eq(payments[:project_id]))))
вызывает исключение: ActiveRecord :: StatementInvalid : PG :: SyntaxError: ERROR: подзапрос должен возвращать только один столбец.
Один из способов, которым я смог это сделать, был что-то вроде: Project.where(projects[:created_at].gt(6.months.ago)).or(Project.where(id: Project.joins(:payments).select(:id)))
, который сгенерировал SQL SELECT "projects".* FROM "projects" WHERE (("projects"."created_at" > '2019-08-19 09:11:22.064298') OR "projects"."id" IN (SELECT "projects"."id" FROM "projects" INNER JOIN "payments" ON "payments"."project_id" = "projects"."id"))
Это лучший способ сделать это или есть лучший способ? Пожалуйста, можно объединить более 10 таких предложений, включающих несколько таблиц, с использованием include
во всех возможных таблицах, чтобы сделать все отдельные предложения совместимыми, вероятно, будет слишком дорого.