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.