我有两个型号。
- 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
我使用验证来验证每个父母的孩子的存在,所以我不能保留没有孩子的父母。
parent = Parent.new :name => "Jose"
parent.save
#=> false
parent.children_attributes = [{:name => "Pedro"}, {:name => "Emmy"}]
parent.save
#=> true
验证工作。然后我们将通过_destroy
属性
parent.children_attributes = {"0" => {:id => 0, :_destroy => true}}
parent.save
#=> true !!!
parent.reload.children
#=> []
所以我可以通过嵌套表单销毁所有孩子,验证将通过。
实际上发生这种情况是因为我通过_delete
从父母那里删除了孩子后,在重新加载之前,children方法仍然会返回被破坏的对象,因此验证通过了:
parent.children_attributes = {"0" => {:id => 0, :_destroy => true}}
parent.save
#=> true !!!
parent.children
#=> #<Child id:1 ...> # It's actually deleted
parent.reload.children
#=> []
是bug吗?
问题是什么?问题是修复它的最佳解决方案。我的方法是将before_destroy过滤器添加到Child
以检查它是否是最后一个。但它使系统变得复杂。
答案 0 :(得分:60)
这可能对你有用,但我觉得那里有更好的答案。这对我来说听起来像个错误。
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
答案 1 :(得分:0)
这不是一个错误。根据文件
验证指定的 属性不是空白的(如定义的那样) by Object#blank?)
和validates :children, :presence => true
是一样的。文档没有说明如果您尝试在关联上使用它会发生什么。您应该使用validate
。
在关联validates_presence_of
上has_many
关联调用blank?
上使用children
,这是类Array的对象。由于未为blank?
定义Array
,因此会触发在Rails中捕获的method_missing
。通常它会按照您的意愿执行,但我发现它在Rails 3.1rc和Ruby 1.8.7中以一种非常糟糕的方式失败:它默默地还原相关记录的更改。我花了几个小时才知道发生了什么。