diff options
author | Stefan Budeanu <stefan.budeanu@shopify.com> | 2016-12-01 17:39:15 -0500 |
---|---|---|
committer | Stefan Budeanu <stefan.budeanu@shopify.com> | 2016-12-09 11:14:37 -0500 |
commit | 371c083fb0620efebf7bd0188a66486403e12ecc (patch) | |
tree | 4c10587ae04edb22e00e4c0a8d1ba2024786057d /activerecord/test | |
parent | 872faa958398fa5aaf6b0e4cd6a8090503d6885a (diff) | |
download | rails-371c083fb0620efebf7bd0188a66486403e12ecc.tar.gz rails-371c083fb0620efebf7bd0188a66486403e12ecc.tar.bz2 rails-371c083fb0620efebf7bd0188a66486403e12ecc.zip |
Emulate db trigger behaviour for after_commit :destroy, :update
Race conditions can occur when an ActiveRecord is destroyed
twice or destroyed and updated. The callbacks should only be
triggered once, similar to a SQL database trigger.
Diffstat (limited to 'activerecord/test')
-rw-r--r-- | activerecord/test/cases/transaction_callbacks_test.rb | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/activerecord/test/cases/transaction_callbacks_test.rb b/activerecord/test/cases/transaction_callbacks_test.rb index dba100f5c9..391bbe8877 100644 --- a/activerecord/test/cases/transaction_callbacks_test.rb +++ b/activerecord/test/cases/transaction_callbacks_test.rb @@ -449,6 +449,51 @@ class CallbacksOnMultipleActionsTest < ActiveRecord::TestCase end end +class CallbacksOnDestroyUpdateActionRaceTest < ActiveRecord::TestCase + class TopicWithHistory < ActiveRecord::Base + self.table_name = :topics + + def self.clear_history + @@history = [] + end + + def self.history + @@history ||= [] + end + end + + class TopicWithCallbacksOnDestroy < TopicWithHistory + after_commit(on: :destroy) { |record| record.class.history << :destroy } + end + + class TopicWithCallbacksOnUpdate < TopicWithHistory + after_commit(on: :update) { |record| record.class.history << :update } + end + + def test_trigger_once_on_multiple_deletions + TopicWithCallbacksOnDestroy.clear_history + topic = TopicWithCallbacksOnDestroy.new + topic.save + topic_clone = TopicWithCallbacksOnDestroy.find(topic.id) + topic.destroy + topic_clone.destroy + + assert_equal [:destroy], TopicWithCallbacksOnDestroy.history + end + + def test_trigger_on_update_where_row_was_deleted + TopicWithCallbacksOnUpdate.clear_history + topic = TopicWithCallbacksOnUpdate.new + topic.save + topic_clone = TopicWithCallbacksOnUpdate.find(topic.id) + topic.destroy + topic_clone.author_name = "Test Author" + topic_clone.save + + assert_equal [], TopicWithCallbacksOnUpdate.history + end +end + class TransactionEnrollmentCallbacksTest < ActiveRecord::TestCase class TopicWithoutTransactionalEnrollmentCallbacks < ActiveRecord::Base self.table_name = :topics |