Rails Complex Nested Form, validates_presence_of Parent on the Child

The answer should have been easy to find.

But I should just be a better developer and should either have known it or been able to figure it out by myself based on what I do know.

Alas…

Anyway, here’s the sitch: I wrote an inventory management system for Patrick’s small book-selling business. It’s got a lot of dumb stuff in it, especially since I started building it when I was pretty new to writing Ruby on Rails.

We keep track of all the publications, obviously. And the publications are of various types (book, periodical, compact disc, etc.) and have various binding types (hardcover, trade paperback, saddle-stitch, jewel case). So I have:

class Publication < ActiveRecord::Base

[...]

attr_accessible publication_type_id, :binding_type_id [...]

 

[...]

belongs_to :binding_type
accepts_nested_attributes_for :binding_type, :allow_destroy => false, :reject_if => proc { |binding_type| binding_type['name'].blank? }

belongs_to :publication_type
accepts_nested_attributes_for :publication_type, :allow_destroy => false, :reject_if => proc { |publication_type| publication_type['name'].blank? }

[...]

validates_presence_of:publication_type_id, :binding_type_id [...]

[...]

It’s a lot more complicated than that, but this is the pertinent info.

In my publication form, I have nested forms whereby I can add a new publication type or binding type if I need to.

When I actually try to use the form, I get “Publication Type is required” and “Binding Type is required” whenever I try to add a new publication type or binding type.

Obviously, this means the validation of the publication/binding type is happening before the new publication/binding type is being created. So I need to only validate publication/binding type (id) if I’m not submitting a valid, new publication/binding type…

I tried all kinds of finaglin’ based on all kinds of Googling I did, which I won’t go into here, because, if you’re anything like me, you just wanna know what you need to do to make this work.

Instead of this:

validates_presence_of:publication_type_id, :binding_type_id

 

I did this:

validates_presence_of :binding_type_id, :unless => lambda {|publication| publication.binding_type.try(:valid?)}

validates_presence_of :publication_type_id, :unless => lambda {|publication| publication.publication_type.try(:valid?)}

I hope that helps save someone some time. I wasted probably three hours to get there; I’ll be a better programmer if I can learn from that.