Summary: Adding validates_associated method to your parent ActiveRecord classes will ensure both the parent and child class are valid before saving.
In this posting we will use the same model as our last post When Associations Get Saved.
Last time, we established that associated child models are automatically saved when the parent is saved. For example:
account = Account.new(:name => "Nicholas") address = account.build_address.new(:street => "Eva Avenue") account.save! address.new_record? # => false
Here the associated address is saved when account is saved. But how does validation play into the saving of associations?
In this example, we have added no additional validation rules:
account = Account.new(:name => "Nicholas") address = account.build_address(:city => "Ottawa") account.save! # => true account.new_record? # => false address.new_record? # => true
Although the account is valid, the address is not, it is missing the street address. When account is saved, it attempts to save the address model, but it cannot. Typically in this scenario we would prefer that the parent model is not saved if the child model in invalid and cannot be saved. How can we achieve this?
Add the following to your account model:
validates_associated :address
And observe the difference in model behavior:
account = Account.new(:name => "Nicholas") address = account.build_address(:city => "Ottawa") account.save! # => ActiveRecord::RecordInvalid: Validation failed: Address is invalid account.new_record? # => true address.new_record? # => true
As you can see an exception is raised when the account is saved as the address is invalid.
In conclusion, when a dependent model needs to be valid add the validates_associcated method to the parent model.