aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/autosave_association.rb
diff options
context:
space:
mode:
authorGuillaume Malette <gmalette@gmail.com>2018-05-22 15:58:22 -0400
committerRafael França <rafaelmfranca@gmail.com>2018-05-22 15:58:22 -0400
commit976ef40aefc92a30ca44a1b0322e5b46e32c0d91 (patch)
treeef6be483cb67e3f9c3804d267f9914d1eedc54c1 /activerecord/lib/active_record/autosave_association.rb
parent9385a5b5854567a059997d59001ddee0d35c7ed2 (diff)
downloadrails-976ef40aefc92a30ca44a1b0322e5b46e32c0d91.tar.gz
rails-976ef40aefc92a30ca44a1b0322e5b46e32c0d91.tar.bz2
rails-976ef40aefc92a30ca44a1b0322e5b46e32c0d91.zip
Rollback parent transaction when children fails to update (#32796)
* Rollback parent transaction when children fails to update Rails supports autosave associations on the owner of a `has_many` relationship. In certain situation, if the children of the association fail to save, the parent is not rolled back. ```ruby class Employee < ActiveRecord::Base end class Company < ActiveRecord::Base has_many(:employees) end company = Company.new employee = company.employees.new company.save ``` In the previous example, if the Employee failed to save, the Company will not be rolled back. It will remain in the database with no associated Employee. I expect the `company.save` call to be atomic, and either create all or none of the records. The persistance of the Company already starts a transaction that nests it's children. However, it didn't track the success or failure of it's children in this very situation, and the outermost transaction is not rolled back. This PR makes the change to track the success of the child insertion and rollback the parent if any of the children fail. * Change the test to reflect what we expect Once #32862 is merged, rolling back a record will rollback it's state to match the state before the database changes were applied * Use only the public API to express the tests * Refactor to avoid reassigning saved for nested reflections [Guillaume Malette + Rafael Mendonça França]
Diffstat (limited to 'activerecord/lib/active_record/autosave_association.rb')
-rw-r--r--activerecord/lib/active_record/autosave_association.rb7
1 files changed, 5 insertions, 2 deletions
diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb
index a1250c3835..9575cc24c8 100644
--- a/activerecord/lib/active_record/autosave_association.rb
+++ b/activerecord/lib/active_record/autosave_association.rb
@@ -400,8 +400,11 @@ module ActiveRecord
if autosave != false && (@new_record_before_save || record.new_record?)
if autosave
saved = association.insert_record(record, false)
- else
- association.insert_record(record) unless reflection.nested?
+ elsif !reflection.nested?
+ association_saved = association.insert_record(record)
+ if reflection.validate?
+ saved = association_saved
+ end
end
elsif autosave
saved = record.save(validate: false)