在嵌套表单中,我希望用户能够同时创建或修改所有Parent
的Childs
。因此,让我们使传递的PARAMS是这样的:Rails如何验证跨嵌套子对象的唯一性
{"childs_attributes" => [{attribute:1}, {attribute:2}, {attribute:3}...]}
我想验证,对于任何一个Parent
称,attribute
一切都其Childs
必须是唯一的。换句话说,在上面的例子中,这是可以的,因为你会得到:
Parent.childs.pluck(:attribute).uniq.length == Parent.childs.pluck(:attribute).length
但是,如果PARAMS传递就像下面,这将会是验证规则的违反:
{"childs_attributes" => [{attribute:1}, {attribute:2}, {attribute:3}...]}
到目前为止,我已经想出来做这个验证的唯一解决方案是在Controller中......我知道这是不好的做法,因为我们想把它推到模型上。
的问题是,如果在模型中我有类似下面:
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)
不会返回在当前的更新通过attribute
,因为当前的更新拿下还没有储蓄。
我想我可以做一些类似于after_save
的东西,但是这感觉真的很复杂,因为它回溯并颠倒了数据库提交(更不用说,下面写的代码[未经测试,只是一个例子]可能导致循环循环如果我不小心,因为父验证关联的孩子)
after_save :unique_attribute_on_child
def unique_attribute_on_child
attribute_list = self.childs.pluck(:attribute)
if attribute_list.uniq.length != attribute_list.length
self.childs.each { |c| c.update_attributes(attribute:nil) }
errors[:base] << "Parent contains Child(s) with same Attribute"
end
end
end
其他想法?