嵌套模型和父验证 [英] Nested models and parent validation
问题描述
我有两个模型.
-Parent
有很多 Children
;
-Parent
accepts_nested_attributes_for Children
;
I've got two models.
- Parent
has_many Children
;
- Parent
accepts_nested_attributes_for Children
;
class Parent < ActiveRecord::Base
has_many :children, :dependent => :destroy
accepts_nested_attributes_for :children, :allow_destroy => true
validates :children, :presence => true
end
class Child < ActiveRecord::Base
belongs_to :parent
end
我使用验证来验证每个父母是否有孩子,所以我不能在没有孩子的情况下保存父母.
I use validation to validate presence of children for every parent, so I can't save parent without children.
parent = Parent.new :name => "Jose"
parent.save
#=> false
parent.children_attributes = [{:name => "Pedro"}, {:name => "Emmy"}]
parent.save
#=> true
验证有效.然后,我们将通过_destroy
属性销毁孩子:
validation works. Then we will destroy children via _destroy
attribute:
parent.children_attributes = {"0" => {:id => 0, :_destroy => true}}
parent.save
#=> true !!!
parent.reload.children
#=> []
所以我可以通过嵌套表格销毁所有子级,并且验证将通过.
so I can destroy all children via nested forms and validation will pass.
实际上发生这种情况是因为在通过_delete
从父级删除子级之后,子级方法在重新加载子级对象之前仍会返回已销毁的对象,因此验证通过了:
Actually that happens because after I delete child from my parent via _delete
, children method still returns destroyed object before I reload it, so validation passed:
parent.children_attributes = {"0" => {:id => 0, :_destroy => true}}
parent.save
#=> true !!!
parent.children
#=> #<Child id:1 ...> # It's actually deleted
parent.reload.children
#=> []
是虫子吗?
有什么问题.问题是修复它的最佳解决方案.我的方法是在Child
上添加before_destroy过滤器,以检查它是否为最后一个.但这会使系统变得复杂.
What is the question. The question is best solution to repair it. My approach is to add before_destroy filter to Child
to check if it is last one. But it makes system complicated.
推荐答案
这可能对您有用,但是我觉得那里有一个更好的答案.对我来说,这听起来像是个虫子.
This will probably work for you, but I have a feeling there's a much better answer out there. It sounds like a bug to me.
class Parent < ActiveRecord::Base
validate :must_have_children
def must_have_children
if children.empty? || children.all?(&:marked_for_destruction?)
errors.add(:base, 'Must have at least one child')
end
end
end
这篇关于嵌套模型和父验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!