Validating Existence of a Nested Model in Rails

Posted by Daniel on 03/05/2010

I'm a big fan of Nested Attributes in Rails. It makes my head hurt less, and makes my forms look better. I did have trouble wrapping my head around one aspect of Nested Attributes through, and that was ensuring that a user could not have less than X associated models after a save or update.

Consider this:
#app/models/user.rb
class User < ActiveRecord::Base
 has_many :addresses
 accepts_nested_attributes_for :addresses, :allow_destroy => true, :reject_if => lambda {|a| a[:city].blank?}
end

#app/models/address.rb
class Address < ActiveRecord::Base
 belongs_to :user
end

We know that the user model needs to have at least one address. How do you test for that though? If the user selects to mark all the records for deletion without creating a new one, we're screwed. Digging through the API I found the "marked_for_destruction?" method, and the answer to my question.

The Solution:
#app/models/user.rb
class User < ActiveRecord::Base
 has_many :addresses
 accepts_nested_attributes_for :addresses, :allow_destroy => true, :reject_if => lambda {|a| a[:city].blank?}
 validate :at_least_one_address  private  def at_least_one_address   delCount = 0   self.addresses.each {|a| delCount += 1 if a.marked_for_destruction?} #iterate through each record and check if it's going to be deleted   errors.add_to_base "You must have at least one address entered." if delCount >= self.addresses.length #if our number of records about to be deleted is greater than or equal to our number of addresses, we raise an error  end end

As always, I hope this saves someone some time!

Comments.

No comments yet.

Name: (required)

Email: (not shown or published)

Website Url:


(Use Markdown Syntax, <pre> your code </pre>)