【发布时间】:2020-02-19 14:18:46
【问题描述】:
有项目模型和支付模型:
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: subquery must return only one column.
我能够做到的一种方法是:
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 以使所有单独的子句兼容可能太昂贵了。
【问题讨论】:
标签: ruby-on-rails arel