Rails如何使用嵌套表单跨子对象验证唯一性

时间:2016-07-08 05:57:27

标签: ruby-on-rails validation ruby-on-rails-4 activerecord callback

在嵌套表单中,我希望用户能够同时创建或修改所有Parent的{​​{1}}。所以,让我们传递的参数是这样的:

Childs

我希望对任何一个{"childs_attributes" => [{attribute:1}, {attribute:2}, {attribute:3}...]} 进行验证,其所有Parent的{​​{1}}必须是唯一的。换句话说,在上面的例子中,没关系,因为你得到:

attribute

但是,如果通过的参数如下所示,则违反了验证规则:

Childs

到目前为止,我提出进行此验证的唯一解决方案是在控制器中......我知道这是一种不好的做法,因为我们希望将其推送到模型中。

问题在于,如果在模型中我有类似下面的内容:

Parent.childs.pluck(:attribute).uniq.length == Parent.childs.pluck(:attribute).length

这不起作用,因为{"childs_attributes" => [{attribute:1}, {attribute:2}, {attribute:3}...]} 不会返回当前更新中传递的class Parent validate :unique_attribute_on_child def unique_attribute_on_child attribute_list = self.childs.pluck(:attribute) if attribute_list.uniq.length != attribute_list.length errors[:base] << "Parent contains Child(s) with same Attribute" end end end ,因为当前更新尚未保存。

我想我可以做一些像self.childs.pluck(:attribute)这样的事情但是感觉真的很复杂,因为它会回来并反转db提交(更不用说,下面编写的代码[未经测试,只是一个例子]可能导致如果我不小心,循环循环,因为父验证相关的孩子)

attribute

其他想法?

1 个答案:

答案 0 :(得分:3)

我的第一个冲动是建议Rails使用智能复数并尝试使用children而不是childs,但我认为这只是一个例子。

我现在建议您改变策略。像这样调用孩子的验证:

class Child < ActiveRecord::Base 
  belongs_to :parent
  ...
  validates :child_attribute, uniqueness: { scope: :parent }
  ...
end