嵌套模型和父验证 [英] Nested models and parent validation

查看:70
本文介绍了嵌套模型和父验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个模型.
-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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆