我有一个rails 3.2应用程序,其中我有一个简单的父/子关系,我需要使用父级的值来验证子级中的属性。模型看起来像这样:
class RubricItem < ActiveRecord::Base
attr_accessible :max_score, :min_score, :name, :order
has_many :rubric_ranges
end
和
class RubricRange < ActiveRecord::Base
attr_accessible :helper, :range_max, :range_min, :rubric_item_id
validates_presence_of :helper, :range_max, :range_min
validates :range_max, :range_min, :numericality => {:only_integer => true}
validates :range_max, :numericality => { :greater_than => :range_min }
belongs_to :rubric_item
end
我希望能够验证两种不同的东西。首先,对于rubric_range,我想验证其range_min值是&gt; =对其父级rubic.min_score,以及range_max&lt; =到其父级rubric.max_score。
其次,我想验证其他rubric_ranges是否具有唯一的最小/最大值。换句话说,不能为同一个值定义两个rubric_range,因此如果一个覆盖0-2,则另一个不能在其范围内包含0,1或2。示例:第一个范围是0-2,如果一个定义2-4范围,我想在父级范围内引发验证错误。
感谢您的帮助。
答案 0 :(得分:2)
您几乎可以像使用父级一样使用父级:
class RubricRange < ActiveRecord::Base
...
validate :has_proper_range
...
def has_proper_range
error.add(:range_min, ' cannot be smaller than RubricItem minimum score') if range_min < rubric_item.min_score
error.add(:range_max, ' cannot be greater than RubricItem maximum score') if range_max > rubric_item.max_score
end
唯一的问题是如果你想使用nested_attributes与RubricItem一起创建RubricRange项目,因为关联的构建方法不会为新记录设置反向关系。
第二次验证可以通过简单地注意到,如果在给定范围内存在min或max的任何其他范围则会失败。因此:
validate :do_not_overlap_with_other_ranges
...
def do_not_overlap_with_other_ranges
overlapping_ranges = self.class.where('(range_min >= :min AND range_min <= :max) OR (range_max >= :min AND range_max <= :max)', {:min => range_min, :max => range_max})
overlapping_ranges = overlapping_ranges.where.not(:id => id) unless new_record?
errors.add(:base, 'Range overlapping with another range') if overlapping_ranges.exists?
end
(请随意评论上面的查询,因为我认为应该有更好的方式来写这个。)