Active Record, Parent-Child Relationships, and Validations

I've been reading through Advanced Rails Recipes, and so far I like the book. It has a nice collection of tips and tricks for the experienced Rails developer. This is the kind of book that you have to quickly scan through when you get it, so you know what tips are available. Remembering that the book has the solution for your problem at hand is the tough part.

One common requirement for web frameworks is being able to handle nested forms on submit. It's too common to present to the user a complex form, representing many different, usually nested, objects. The difficulty isn't really in displaying or formatting the nested HTML form itself, but in handling the submit. How do you save or update all of the objects easily and efficiently? What if there's an error?

The excellent and always useful RailsCasts had a series of episodes that handle the nested form issue (Complex Forms 1, Complex Forms 2, and Complex Forms 3).

There's a problem with their approach, and it's cause is validations. There's a chicken-and-the-egg problem, in that if you wish to add a validates_presence_of :parent_id in your nested child object (which you should, because it helps to enforce referential integrity), then you will not be able to save the parent and the child objects with a simple call to parent.save

Remember, the whole point of the RailsCasts, and this general problem, is that we wish to easily handle nested forms when submitted. We want to create a parent and its children with one simple submit.

Here's what happens, thought:


  1. class Parent has many Children, class Child belongs to Parent. Class Child also validates_presence_of parent_id

  2. create a new parent

  3. create a new child with parent.children.build()

  4. call parent.save

  5. the save will fail, because child is invalid, because parent_id is null, because validations for children are run before parents are saved (and thus, create a PK)



(oh, and did you know that when saving a new parent that has new children, the parent will cascade the validations down to the children automatically? I didn't know this was automatic)

Getting back to Advanced Rails Recipes, the author included the Complex Forms examples from RailsCasts. And there's no mention of this validation issue. So, being the good beta book tester that I am, I created an errata suggesting the mention this problem with validations.

Note, someone with the name of Mina Naguib mentioned this problem in the comments for Complex Forms 1, although I haven't tried it out (and sorry for not linking to the comment, the RailsCasts blog doesn't provide an id for each comment).

So, IMO, this is a common requirement of web frameworks that I don't believe Rails has solved cleanly and elegantly yet. I'll keep looking around for a good solution. Suggestions welcome!
3 comments

Popular posts from this blog