When to use “validates_associated” v “validate => true”

I had to dig into the Rails (3.0.7) code to find some differences. The core functionality looks the same to me — they both seem to call valid? on the associated record(s).

The key differences that I did find only appear when using the :autosave feature or when either destroying the associated object or marking it for destruction. For example, I have:

class AbsentDate < ActiveRecord::Base
  belongs_to :user, :autosave => true, :validate => true
end

And I see the following behaviour:

user = User.new(:username => "Jimmy")
user.valid?                               # => true
ad = AbsentDate.new(:user => user)
user.username = nil                          
user.valid?                               # => false
ad.valid?                                 # => false
ad.errors.full_messages                   # => ["User username cannot be empty"]
ad.user.mark_for_destruction
ad.valid?                                 # => true

Note that marking the user for destruction resulted in a valid AbsentDate. Also note that there is only one error message. Now consider this case:

class AbsentDate < ActiveRecord::Base
  belongs_to :user, :autosave => true
  validates_associated :user
end

This is what I see happening:

user = User.new(:username => "Jimmy")
user.valid?                                # => true
ad = AbsentDate.new(:user => user)
user.username = nil
user.valid?                                # => false
ad.valid?                                  # => false
ad.errors.full_messages                    # => ["User username cannot be empty", "User is invalid"]
ad.user.mark_for_destruction
ad.valid?                                  # => false

Two error messages this time, and the AbsentDate is still false even though its user has been marked for destruction. I was able to replicate these results by calling destroy instead of mark_for_destruction.

One last thing: if you use validates_associated, you get several options (:if, :unless, :on, :message) that you won’t have if you use the flag on belongs_to.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)