【问题标题】:rails validating multiple child models in a complex formrails 以复杂的形式验证多个子模型
【发布时间】:2009-08-17 13:33:11
【问题描述】:

我正在以复杂的形式使用多个子模型(例如http://railsforum.com/viewtopic.php?id=28447)。表单效果很好,但在将表单数据输入数据库之前,我需要验证子模型 set 的属性。我想出了一种主要工作,非常笨拙的方式来做到这一点。看来必须有更好的方法,所以我正在寻求建议......

基本上一个人有_many分布。分布具有(除其他外)百分比属性。对于给定的人,他们的分配必须总计 100% 才有效。这对我来说是“交易”,但我认为我应该先给验证者一个机会。

我尝试将其编写为自定义验证器,但验证器仅适用于已保存到数据库中的数据。它没有检查表单提交的参数。换句话说,我能够通过表单输入无效的百分比,这些百分比被保存,然后由于模型中已经存在错误数据,随后的编辑都失败了。

接下来我在我的 Person 模型中扩展了 update_attributes,添加了一个事务:

def update_attributes(params)
  retval = true
  self.transaction do
    retval = super

    unless distributions_exactly_100?
      retval = false
      errors.add_to_base("Distribution must add up to exactly 100%")
      raise ActiveRecord::Rollback
    end
  end
  retval
end

retval 业务很难看,但这或多或少是有效的(有时,当它发现错误并重新渲染时,表单中会缺少一些待处理的分发版)。还有一个细微的差别让我相信这是一个糟糕的方法:如果我的分布关联是用辅助方法定义的,如下所示,我不能在我的update_attributes()(或distributions_exactly_100?)中使用辅助方法,因为它们转到数据库,而不是对刚刚分配但尚未提交的分布集进行操作。

 has_many :distributions do
   def for_month_and_year(month, year)
     find :all, :conditions => ['month = ? and year = ?', month, year]
   end

   def total_for_month_and_year(month, year)
     sum :percentage, :conditions => ['month = ? and year = ?', month, year]
   end

   ...

   def years_and_months
     ds = find(:all, :order => 'year DESC, month DESC')
     (ds.collect {|d| [d.year, d.month]}).uniq
   end

 end

我能想到的唯一另一件事是在进入 update_attributes 的过程中将参数本身作为文本处理。但那是错误的。 :)

还有其他人对整个儿童集合进行验证吗?正确的做法是什么?

【问题讨论】:

    标签: ruby-on-rails validation children nested-forms associations


    【解决方案1】:

    我不建议在update_attributes 中设置错误。将验证保留在正常位置。

    回到您的问题,您能否更改验证检查以处理内存中的分布而不是在数据库上执行计算?

    # in Person model
    validate :ensure_distributions_equal_100
    
    def ensure_distributions_equal_100
      percent = distributions.map(&:percent).sum
      if percent != 100
        errors.add_to_base("Distribution must add up to exactly 100%, they are #{percent}")
      end
    end
    

    【讨论】:

    • 是的,谢谢,我确实写了一个函数,一旦我弄清楚了内存与 DB 的角度,就可以调用它作为验证。 :) 我仍然对验证失败时如何呈现编辑视图有问题(一些未决更改丢失,但不是全部丢失),但这是一个不同的错误!
    猜你喜欢
    • 1970-01-01
    • 2016-07-24
    • 1970-01-01
    • 1970-01-01
    • 2020-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多