MarkMT
2013-Feb-17 23:07 UTC
Inconsistent validation behavior for has_many :through association
The API documentation for ActiveRecord associations here:
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html,
says:
- Adding an object to a collection (has_many or has_and_belongs_to_many)
automatically saves that object, except if the parent object (the owner of
the collection) is not yet stored in the database.
- If saving any of the objects being added to a collection (via push or
similar) fails, then push returns false
Similarly in the Rails Guides -
http://guides.rubyonrails.org/association_basics.html#has_many-association-reference
:
-------------
4.3.3 When are Objects Saved?
When you assign an object to a has_many association, that object is
automatically saved (in order to update its foreign key). If you assign
multiple objects in one statement, then they are all saved.
If any of these saves fails due to validation errors, then the assignment
statement returns false and the assignment itself is cancelled.
-------------
This all seems to work fine for regular has_many associations, but for
has_many :through associations if I add an invalid record to an existing
parent via << I get an ActiveRecord::RecordInvalid exception rather than
false. Looking at the code, it is evident why...
associations/collection_proxy.rb
======================class ActiveRecord::Associations:CollectionProxy
def <<(*records)
proxy_association.concat(records) && self
end
alias_method :push, :<<
end
associations/has_many_through_association.rb
=================================class
ActiveRecord::Associations::HasManyThroughAssociation <
HasManyAssociation
def concat(*records)
unless owner.new_record?
records.flatten.each do |record|
raise_on_type_mismatch(record)
record.save! if record.new_record?
end
end
super
end
end
Since the record is saved with save!, an invalid record raises the
exception.
Is this unintended, or is the documentation misleading?
--
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Core" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to rubyonrails-core+unsubscribe@googlegroups.com.
To post to this group, send email to rubyonrails-core@googlegroups.com.
Visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.