嵌套模型和父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_of
为blank?
对于关联children
,这是Array类的一个对象。 由于blank?
没有为Array
定义,它触发了被Rails捕获的method_missing
。 通常它做你想做的,但我发现它在一个非常糟糕的方式在Rails 3.1rc和Ruby 1.8.7失败:它静静地恢复相关logging的变化。 我花了几个小时才知道发生了什么事情。