3

在对父对象执行验证之前,我需要找到一种方法来让 rails (3.2.8) 保存嵌套属性。我已经搜索了很长时间来寻找我的问题的答案,虽然我发现了类似的问题,但我还没有看到一个优雅的解决方案。

情况如下:

我有一个 activity_log,其中每个 log_entry 都有多个活动。log_entry 有一个名为“hours”的字段,表示当天工作的总时间。每个活动还有一个“小时”字段,表示在该活动上花费的时间。我需要确保 log_entry.activities.sum(:hours) 不大于 log_entry.hours。

这是代码:

class LogEntry < ActiveRecord::Base
  attr_accessible :date, :hours, :activities_attributes

  has_many :activities
  accepts_nested_attributes_for :activities

  validate :sum_hours_not_more_than_total_hours

  private
  def sum_hours_not_more_than_total_hours
    unless activities.sum(:hours) <= hours
      errors.add(:hours, "Hours cannot exceed total hours")
    end
  end
end

问题是它在计算活动时检查数据库,而不是检查参数中的新数据。因此,如果我将 log_entry 的小时数设置为 4 并创建一个小时数设置为 5 的活动,它将无错误地保存(因为 db 说 activity.sum(:hours) == 0)。但是,如果我编辑同一条记录并将活动的小时数设置为 4,它将给出错误(因为数据库说活动.sum(:小时)== 5),它应该通过。

我在这里找到了一种解决方法:http ://railsforum.com/viewtopic.php?id=41562 ,但我希望有一种更优雅的方法来解决这个问题。(实际上,这个解决方案并不像描述的那样对我有用,因为它假设唯一的问题是记录正在通过不应该通过的验证。我也有记录应该通过时验证失败的问题。我想我可以修复它通过跳过验证步骤然后在控制器中进行 sum_hours_not_more_than_total_hours 之类的检查(保存后),但我真的很喜欢从验证中获得的安全感。)

4

1 回答 1

2

您可以像这样根据活动集合计算内容,而不是使用求和查询来访问数据库

self.activities.map(&:hours).sum
于 2013-08-10T19:28:25.877 回答