Validating Existence of a Nested Model in Rails
Posted by Daniel on 03/05/2010I'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!

No comments yet.