如果我问这个问题不好,我很抱歉。我有一个Rails 3.1应用程序与模型(简化),如:
class Employee < ActiveRecord::Base
has_many :merged_children, :class_name => 'Employee', :foreign_key => "merge_parent_id"
has_many :timesheets
def total_time
merged_children.timesheets.in_range(range).hours_minutes.sum
end
end
class Timesheet < ActiveRecord::Base
belongs_to :employee
def in_range(range)
# filter records based on transaction_date in range
end
def hours_minutes
(hours + minutes/60.0).to_f
end
end
注意:in_range方法本质上充当范围,而hours_minutes是计算。 hours_minutes对结果数据集中的每个时间表记录有效,然后total_time应对这些值求和并返回金额。
“total_time”方法不起作用,因为employee.merged_children返回一个数组,而时间表是针对单个Employee对象运行的。
有没有办法构建“total_time”,以便它仍然向db发送一个查询?迭代merged_children数组,为每个数组发出一个查询似乎是不优雅的。不确定直接调用Arel表是否有帮助或受到伤害,但我对这些想法持开放态度。
如果我们做对了,生成的SQL应该看起来像:
SELECT sum(hours + minutes/60.0)
FROM employees e1 join employees e2 on e1.id = e2.merge_parent_id join timesheets t on t.employee_id = e2.id
WHERE e1.id = [@employee.id] and t.transaction_date BETWEEN [@range.begin] and [@range.end]
非常感谢!
答案 0 :(得分:0)
未经测试的实际数据。
range = ((1.day.ago)...(2.days.ago))
merge_parent = Employee.find(some_id)
Timesheet.where(:transaction_date => range)
.joins(:employee).where(:employees => {:merge_parent_id => merge_parent.id})
.sum('hours*60 + minutes')
(0.3ms) SELECT SUM(hours*60 + minutes) AS sum_id FROM "timesheets" INNER JOIN "employees" ON "employees"."id" = "timesheets"."employee_id" WHERE "employees"."merge_parent_id" = 1 AND ("timesheets"."created_at" >= '2011-12-13 03:04:35.085416' AND "timesheets"."created_at" < '2011-12-12 03:04:
为我返回“0”。所以希望它会为你带来更好的东西
答案 1 :(得分:0)
最简单的方法可能是添加
has_many :children_timesheets, :through => :merged_children, :source => :timesheets
到您的员工模型,
然后(假设in_range实际上是一个范围,或者一个查找的类方法)
children_timesheets.in_range(...)
应该是您感兴趣的时间表集合,您可以执行类似
的操作children_timesheets.in_range(...).collect(&:hours_minutes).sum