我有两个带连接表的基本模型。我已经添加了一个范围来计算关系中的计数,并将其作为属性/ psuedo-column公开。一切正常,但我现在想查询列的子集并包含计数列,但我不知道如何引用它。
tldr;如何在我的Arel查询中包含聚合(如计数),同时还要选择列的子集?
模型为Employer
和Employee
,通过Job
加入。这是Employer
的相关代码:
class Employer < ApplicationRecord
belongs_to :user
has_many :jobs
has_many :employees, through: :jobs
scope :include_counts, -> do
left_outer_joins(:employees).
group("employers.id").
select("employers.*, count(employees.*) as employees_count")
end
end
这允许我向雇主加载计数:
employers = Employer.include_counts.where(id: 1)
然后引用计数:
count = employers[0].employees_count
我在我的控制器中加载记录,然后呈现它。但是,我不想渲染超出我需要的字段。在添加计数之前,我可以这样做:
employers = Employer.where(id: 1).select(:id, :name)
当我添加include_counts
范围时,它基本上忽略了select()
。它并没有失败,但最终包括所有列,因为我的范围内有这一行:
select("employers.*, count(employees.*) as employees_count")
如果我从范围中移除employers.*
,那么无论是否有select()
条款,我都不会在结果中获得任何列。
我试过了:
employers = Employer.include_counts.where(id: 1).select(:id, :name, :employee_counts)
...但是会产生以下SQL:
SELECT employers.*, count(employees.*) as employees_count, id, name, employees_count FROM
...和SQL错误,因为列employees_count
不存在且id
和name
不明确。
唯一有用的是:
employers = Employer.include_counts.where(id: 1).select("employers.id, employers.name, count(employees.*) as employees_count")
...但实际上选择employers
中的所有列,由于scope子句再次出现。
如果可以避免,我也不希望原始SQL泄漏到我的控制器中。使用Rails / Arel是否有更惯用的方法?
如果我找不到另一种方法来进行查询,我可能会在模型中创建另一个范围或自定义查找程序,以便控制器代码更清晰。我也愿意接受这样做的建议,但是我想知道是否有一种简单的方法来引用像这样的计算聚合列,就好像它们是任何其他列一样。