Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nested models and parent validation

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.

like image 753
fl00r Avatar asked Feb 28 '11 16:02

fl00r


1 Answers

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 
like image 114
John Douthat Avatar answered Oct 04 '22 07:10

John Douthat