class Project
has_many :tasks
monetize :budget_cents # to create :budget
end
class Task
belongs_to :project
monetize :cost_cents # to create :cost
end
我想为Project.over_budget
创建一个范围,该范围涉及对相关任务的成本求和。
在我看来,它看起来像这样:
scope :over_budget, ->{ where('budget_cents <= ?', tasks.map(&:cost_cents).sum) }
我尝试过的其他事情:
scope :over_budget, -> { joins(:tasks).where('budget <= ?', tasks.map(&:cost).sum) }
scope :over_budget, -> { |proj| joins(:tasks).where('budget <= ?', proj.tasks.map(&:cost).sum) }
scope :over_budget, -> { |proj| where('budget <= ?', Task.where('project_id=?', proj.id).map(&:cost).sum) }
scope :over_budget, -> { |proj| joins(:tasks).where('budget <= ?', Tasks.where('project_id=?', proj.id).map(&:cost).sum) }
这实际上返回没有错误,但是对于所有任务,而不是相关的:
scope :over_budget, ->{ where('budget_cents <= ?', Task.map(&:cost_cents).sum) }
我确定我缺少明显的东西,但是看不到。
答案 0 :(得分:1)
class Project < ApplicationRecord
# ...
scope :over_budget, -> { joins(:tasks).group(:id).having('sum(tasks.cost_cents) > budget_cents') }
end
@chiperific编辑:
上面引发了ambiguous
错误,但是当我稍加修改后它就起作用了:
class Project < ApplicationRecord
# ...
scope :over_budget, -> { joins(:tasks).group(:id).having('sum(tasks.cost_cents) > projects.budget_cents') }
end
Project.joins(:tasks)
的结果如下:
| projects.id | projects.budget_cents | tasks.id | tasks.cost_cents |
| ----------- | --------------------- | -------- | ---------------- |
| 1 | 5 | 1 | 2 |
| 1 | 5 | 2 | 3 |
| 1 | 5 | 3 | 1 |
| 2 | 10 | 4 | 1 |
然后,将.group(:id)
附加到上面的Project.joins(:tasks)
上,现在结果如下:
| projects.id | projects.budget_cents | tasks.id | tasks.cost_cents |
| ----------- | --------------------- | -------- | ---------------- |
| 1 | 5 | 1 | 2 |
| 2 | 10 | 4 | 1 |
然后,最后将.having('sum(tasks.cost_cents) > budget_cents')
附加到Project.joins(:tasks).group(:id)
上,现在结果类似于:
| projects.id | projects.budget_cents | tasks.id | tasks.cost_cents | sum(tasks.costs_cents) |
| ----------- | --------------------- | -------- | ---------------- | ---------------------- |
| 1 | 5 | 1 | 2 | 6
projects.id = 2
行已不存在,因为其sum(tasks.costs_cents)
仅等于1