验证 has_many 关系中的属性总和
Posted
技术标签:
【中文标题】验证 has_many 关系中的属性总和【英文标题】:Validation of sum of attributes from has_many relationship 【发布时间】:2014-09-16 15:43:13 【问题描述】:使用以下 Ruby on Rails 模型“Foo”:
class Foo < ActiveRecord::Base
has_many :bars
accepts_nested_attributes_for :bars
def bar_value_total
self.bars.sum(:value) #TODO: must verify this is in range (0.0 .. 100.0)
end
end
而 Bar 是一个具有单值属性的简单模型:
class Bar < ActiveRecord::Base
validates :value, :inclusion => :in => 0.0..100.0 , :presence => true
end
如果总 Bars 中的值不在指定范围 (0.0 .. 100.0) 内,我如何添加验证以防止保存 Foo?
例如,如果 Foo 具有三个值分别为 40.0 和 50.0 的 Bars,则在添加第三个 Bar 且大于 10.0 时,保存尝试应该会失败。
如果 Foo 已经有一个值为 100.0 的 Bar,如果添加的 Bar 值超过 0.0,则 Save 尝试应该失败。
更新: 我向 Bar 模型添加了一个自定义验证(并且它有效)......但它似乎有点笨拙。还有比这更好的“Rails 方式”吗?
class Bar < ActiveRecord::Base
validates :value, :inclusion => :in => 0.0..100.0 , :presence => true
validate :bar_totals_are_within_range
private
def bar_totals_are_within_range
if !self.foo.bar_value_total + self.value - self.value_was).between?(0.0, 100.0)
errors.add(:base, "Total bar value exceeded")
end
end
end
【问题讨论】:
做一个custom validation。 我添加了一个自定义验证,但它似乎有点脏。想知道有没有更好的方法。 (见更新) 没有内置的 Rails 方法可以做到这一点。所以,是的,它可能有点“脏”。 【参考方案1】:我会说:
accepts_nested_attributes_for :bars, :reject_if => :any_invalid_bar?
def any_invalid_bar?
bars.any? &:invalid?
end
这种方式会在保存一个Foo
之前使用您在Bar
中编写的任何验证来验证每个Bar
。
【讨论】:
以上是关于验证 has_many 关系中的属性总和的主要内容,如果未能解决你的问题,请参考以下文章
ruby on rails has_many 关系表单验证孩子