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
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.
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 #=> []
Is it bug?
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With