嵌套模型和父validation

我有两个模型。
Parent has_many Children ;
Parent accepted_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 

我使用validation来validation每个父母的孩子的存在,所以我不能救孩子没有父母。

 parent = Parent.new :name => "Jose" parent.save #=> false parent.children_attributes = [{:name => "Pedro"}, {:name => "Emmy"}] parent.save #=> true 

validation工作。 那么我们将通过_destroy属性来销毁儿童:

 parent.children_attributes = {"0" => {:id => 0, :_destroy => true}} parent.save #=> true !!! parent.reload.children #=> [] 

所以我可以通过嵌套的forms销毁所有的孩子,validation将通过。

其实这是因为我通过_delete从父母删除孩子之后,子方法仍然返回被销毁的对象之前我重新加载它,所以validation通过:

 parent.children_attributes = {"0" => {:id => 0, :_destroy => true}} parent.save #=> true !!! parent.children #=> #<Child id:1 ...> # It's actually deleted parent.reload.children #=> [] 

是错误吗?

什么是问题。 问题是最好的解决scheme来修复它。 我的方法是添加before_destroy筛选器以检查是否是最后一个。 但是这使系统变得复杂。

这可能会为你工作,但我有一种感觉,有一个更好的答案在那里。 这听起来像是一个bug。

 class Parent validate :must_have_children def must_have_children if children.empty? or children.all? {|child| child.marked_for_destruction? } errors.add(:base, 'Must have at least one child') end end end 

这不是一个错误。 根据文件

validation指定的属性不是空白的(由Object#blank定义)

validates :children, :presence => true是一样的。 如果您尝试在关联上使用它,文档不会说明会发生什么情况。 您应该使用validation使用自定义validation。

has_many关联调用上使用validates_presence_ofblank? 对于关联children ,这是Array类的一个对象。 由于blank? 没有为Array定义,它触发了被Rails捕获的method_missing 。 通常它做你想做的,但我发现它在一个非常糟糕的方式在Rails 3.1rc和Ruby 1.8.7失败:它静静地恢复相关logging的变化。 我花了几个小时才知道发生了什么事情。