A better validates_associated
As you may very well know, validates_associated is good, but not great. Yes, it does ensure that your related models adhere to the rules in your multi-model form. But there are two fundamental problems with it:
- The actual error messages are useless (i.e. “[Model] is invalid”) — I’d like to know why it’s invalid
- Redundant messages for each and every invalid associated model
The first, everyone can agree on. So let’s fix that one right away:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | # config/initializers/validation_fixes.rb module ValidatesAssociatedAttributes module ActiveRecord::Validations::ClassMethods def validates_associated(*associations) class_eval do validates_each(associations) do |record, associate_name, value| (value.respond_to?(:each) ? value : [value]).each do |rec| if rec && !rec.valid? rec.errors.each do |key, value| record.errors.add(key, value) end end end end end end end end |
There, now you’ll get the true error messages. For example, “[Model] is invalid” now becomes “[Model] is not formatted properly”, or the like.
Now, onto the second one. I find that most of my multi-model forms have more than one nested model. To save you from a contrived example, let’s use Golf Trac. Well, a course has 4 different sets of 18 yardages (72 yardages), 2 sets of 18 handicaps, 18 par ratings, then 1 rating and 1 slope for each of the 4 possible tees (black, blue, white, red). That’s a total of (I think) 134 fields on a course (I know, that’s why courses are now reusable).
So, the course form, when submitted, gets split out into three tables: courses, tees, and holes, each with their own validation rules. Let’s say a user submits a blank form. Originally, validates_associated would say “Hole is invalid” a gajillion times. That’s stupid in my case. I’d rather it just say “Par cannot be blank” and/or “Par must be a number” one time each. So, combined with step #1, I did something like this:
1 2 3 4 5 6 7 | # config/initializers/validation_fixes.rb class ActiveRecord::Errors alias old_full_messages full_messages def full_messages old_full_messages.uniq end end |
Now I get much better error messages and I’m only yelling at the user one time.

sandeep Monday, 07 Sep, 2009 Posted at 09:10AM
hey buddy
Thanx for your post.
i got the following error when i implemented your solution
{:message=>"Address is incomplete or invalid"} is not a symbol
Please help………..
Sarah Allen Tuesday, 15 Sep, 2009 Posted at 08:13AM
Nice. You should file a lighthouse ticket and submit a patch. I would +1 it. BugMash is coming up in a couple of weeks if are new to the rails contribution process :)
Eric A. Saturday, 31 Oct, 2009 Posted at 10:29PM
Great post, exactly what’s needed to enhance the validates_associated method.
@sandeep
I initially encountered a similar issue. However, the easy fix is to remove the :message => “…” part of the validates_associated line, then specify your error messages on the associated models accordingly.
Nick R. Monday, 02 Nov, 2009 Posted at 03:00PM
+1 for rails patch
Chris Rogers Monday, 09 Nov, 2009 Posted at 05:27PM
Works great, appreciated.