嵌套属性的自定义验证 [英] Custom validation on nested attributes

查看:51
本文介绍了嵌套属性的自定义验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I need to find a way to get rails (3.2.8) to save nested attributes before performing validation on the parent object. I've searched a long time for an answer to my problem and, while I've found similar questions, I haven't yet seen an elegant solution.

情况如下:

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

I have an activity_log where each log_entry has multiple activities. The log_entry has a field called 'hours', which represents the total time worked that day. Each activity also has an 'hours' field, representing time spent on that activity. I need to make sure that log_entry.activities.sum(:hours) is not greater than 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 的活动,它将保存而没有错误(因为数据库说活动.sum(:小时)== 0).但是,如果我编辑相同的记录并将活动的小时数设置为 4,它会在它应该通过时给出错误(因为数据库说活动.sum(:hours) == 5).

The problem is that it checks against the db when calculating activities.sum(:hours) instead of checking against the new data in params. So if I set a log_entry's hours to 4 and create an activity with hours set to 5, it will save with no errors (because the db says that activities.sum(:hours) == 0). But if I edit that same record and set the activity's hours to 4 it will give an error (because the db says activities.sum(:hours) == 5), when it should pass.

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

I found a workaround here: http://railsforum.com/viewtopic.php?id=41562, but I was hoping there was a more elegant way of solving this problem. (Actually, this solution doesn't work for me as described because it assumes that the only problem is that records are passing validation that shouldn't. I also have the problem that records fail validation when they should pass. I imagine I could fix it by skipping the validation step and then doing a check like sum_hours_not_more_than_total_hours in the controller (after save), but I really like the sense of security I get from validation.)

推荐答案

您可以像这样根据活动集合计算内容,而不是使用 sum-query 来访问数据库

instead of hitting the database with a sum-query, you could calculate the stuff based of the activities collection like this

self.activities.map(&:hours).sum

这篇关于嵌套属性的自定义验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆