aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorAaron Patterson <aaron.patterson@gmail.com>2012-05-16 16:06:49 -0700
committerAaron Patterson <aaron.patterson@gmail.com>2012-05-16 16:06:49 -0700
commit8e5f07dabcb2d917105aa7ae678072ab44bd5ad4 (patch)
treec49851277d417b067ac86ffc16f228b5faf9c469 /activerecord
parent8bc1e532a92bc259c827f96df61cdb86c5e6baa0 (diff)
parentc8792c7b2ea4f5fe7a5610225433ea8dd8d0f83e (diff)
downloadrails-8e5f07dabcb2d917105aa7ae678072ab44bd5ad4.tar.gz
rails-8e5f07dabcb2d917105aa7ae678072ab44bd5ad4.tar.bz2
rails-8e5f07dabcb2d917105aa7ae678072ab44bd5ad4.zip
Merge pull request #5535 from markmcspadden/issue_5527_rollbacks
Allow manual rollbacks in after_save to reset object correctly
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/lib/active_record/transactions.rb10
-rw-r--r--activerecord/test/cases/transaction_callbacks_test.rb37
2 files changed, 46 insertions, 1 deletions
diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb
index 64e5640791..30e1035300 100644
--- a/activerecord/lib/active_record/transactions.rb
+++ b/activerecord/lib/active_record/transactions.rb
@@ -290,7 +290,15 @@ module ActiveRecord
status = nil
self.class.transaction do
add_to_transaction
- status = yield
+ begin
+ status = yield
+ rescue ActiveRecord::Rollback
+ if defined?(@_start_transaction_state)
+ @_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) - 1
+ end
+ status = nil
+ end
+
raise ActiveRecord::Rollback unless status
end
status
diff --git a/activerecord/test/cases/transaction_callbacks_test.rb b/activerecord/test/cases/transaction_callbacks_test.rb
index 9846f5b12d..961ba8d9ba 100644
--- a/activerecord/test/cases/transaction_callbacks_test.rb
+++ b/activerecord/test/cases/transaction_callbacks_test.rb
@@ -287,8 +287,45 @@ class TransactionObserverCallbacksTest < ActiveRecord::TestCase
raise ActiveRecord::Rollback
end
+ assert topic.id.nil?
+ assert !topic.persisted?
assert_equal %w{ after_rollback }, topic.history
end
+
+ class TopicWithManualRollbackObserverAttached < ActiveRecord::Base
+ self.table_name = :topics
+ def history
+ @history ||= []
+ end
+ end
+
+ class TopicWithManualRollbackObserverAttachedObserver < ActiveRecord::Observer
+ def after_save(record)
+ record.history.push "after_save"
+ raise ActiveRecord::Rollback
+ end
+ end
+
+ def test_after_save_called_with_manual_rollback
+ assert TopicWithManualRollbackObserverAttachedObserver.instance, 'should have observer'
+
+ topic = TopicWithManualRollbackObserverAttached.new
+
+ assert !topic.save
+ assert_equal nil, topic.id
+ assert !topic.persisted?
+ assert_equal %w{ after_save }, topic.history
+ end
+ def test_after_save_called_with_manual_rollback_bang
+ assert TopicWithManualRollbackObserverAttachedObserver.instance, 'should have observer'
+
+ topic = TopicWithManualRollbackObserverAttached.new
+
+ topic.save!
+ assert_equal nil, topic.id
+ assert !topic.persisted?
+ assert_equal %w{ after_save }, topic.history
+ end
end
class SaveFromAfterCommitBlockTest < ActiveRecord::TestCase