aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test/cases/transactions_test.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/test/cases/transactions_test.rb')
-rw-r--r--activerecord/test/cases/transactions_test.rb98
1 files changed, 71 insertions, 27 deletions
diff --git a/activerecord/test/cases/transactions_test.rb b/activerecord/test/cases/transactions_test.rb
index 5cccf2dda5..88e595c39f 100644
--- a/activerecord/test/cases/transactions_test.rb
+++ b/activerecord/test/cases/transactions_test.rb
@@ -2,6 +2,7 @@ require "cases/helper"
require 'models/topic'
require 'models/reply'
require 'models/developer'
+require 'models/computer'
require 'models/book'
require 'models/author'
require 'models/post'
@@ -12,7 +13,7 @@ class TransactionTest < ActiveRecord::TestCase
fixtures :topics, :developers, :authors, :posts
def setup
- @first, @second = Topic.find(1, 2).sort_by { |t| t.id }
+ @first, @second = Topic.find(1, 2).sort_by(&:id)
end
def test_persisted_in_a_model_with_custom_primary_key_after_failed_save
@@ -193,6 +194,16 @@ class TransactionTest < ActiveRecord::TestCase
assert_equal posts_count, author.posts(true).size
end
+ def test_cancellation_from_returning_false_in_before_filter
+ def @first.before_save_for_transaction
+ false
+ end
+
+ assert_deprecated do
+ @first.save
+ end
+ end
+
def test_cancellation_from_before_destroy_rollbacks_in_destroy
add_cancelling_before_destroy_with_db_side_effect_to_topic @first
nbooks_before_destroy = Book.count
@@ -492,35 +503,32 @@ class TransactionTest < ActiveRecord::TestCase
assert topic.frozen?, 'not frozen'
end
- # The behavior of killed threads having a status of "aborting" was changed
- # in Ruby 2.0, so Thread#kill on 1.9 will prematurely commit the transaction
- # and there's nothing we can do about it.
- unless RUBY_VERSION.start_with? '1.9'
- def test_rollback_when_thread_killed
- queue = Queue.new
- thread = Thread.new do
- Topic.transaction do
- @first.approved = true
- @second.approved = false
- @first.save
+ def test_rollback_when_thread_killed
+ return if in_memory_db?
+
+ queue = Queue.new
+ thread = Thread.new do
+ Topic.transaction do
+ @first.approved = true
+ @second.approved = false
+ @first.save
- queue.push nil
- sleep
+ queue.push nil
+ sleep
- @second.save
- end
+ @second.save
end
+ end
- queue.pop
- thread.kill
- thread.join
+ queue.pop
+ thread.kill
+ thread.join
- assert @first.approved?, "First should still be changed in the objects"
- assert !@second.approved?, "Second should still be changed in the objects"
+ assert @first.approved?, "First should still be changed in the objects"
+ assert !@second.approved?, "Second should still be changed in the objects"
- assert !Topic.find(1).approved?, "First shouldn't have been approved"
- assert Topic.find(2).approved?, "Second should still be approved"
- end
+ assert !Topic.find(1).approved?, "First shouldn't have been approved"
+ assert Topic.find(2).approved?, "Second should still be approved"
end
def test_restore_active_record_state_for_all_records_in_a_transaction
@@ -561,6 +569,21 @@ class TransactionTest < ActiveRecord::TestCase
assert !@second.destroyed?, 'not destroyed'
end
+ def test_restore_frozen_state_after_double_destroy
+ topic = Topic.create
+ reply = topic.replies.create
+
+ Topic.transaction do
+ topic.destroy # calls #destroy on reply (since dependent: destroy)
+ reply.destroy
+
+ raise ActiveRecord::Rollback
+ end
+
+ assert_not reply.frozen?
+ assert_not topic.frozen?
+ end
+
def test_sqlite_add_column_in_transaction
return true unless current_adapter?(:SQLite3Adapter)
@@ -627,6 +650,27 @@ class TransactionTest < ActiveRecord::TestCase
assert transaction.state.committed?
end
+ def test_transaction_rollback_with_primarykeyless_tables
+ connection = ActiveRecord::Base.connection
+ connection.create_table(:transaction_without_primary_keys, force: true, id: false) do |t|
+ t.integer :thing_id
+ end
+
+ klass = Class.new(ActiveRecord::Base) do
+ self.table_name = 'transaction_without_primary_keys'
+ after_commit { } # necessary to trigger the has_transactional_callbacks branch
+ end
+
+ assert_no_difference(-> { klass.count }) do
+ ActiveRecord::Base.transaction do
+ klass.create!
+ raise ActiveRecord::Rollback
+ end
+ end
+ ensure
+ connection.drop_table 'transaction_without_primary_keys', if_exists: true
+ end
+
private
%w(validation save destroy).each do |filter|
@@ -634,7 +678,7 @@ class TransactionTest < ActiveRecord::TestCase
meta = class << topic; self; end
meta.send("define_method", "before_#{filter}_for_transaction") do
Book.create
- false
+ throw(:abort)
end
end
end
@@ -698,7 +742,7 @@ if current_adapter?(:PostgreSQLAdapter)
end
end
- threads.each { |t| t.join }
+ threads.each(&:join)
end
end
@@ -746,7 +790,7 @@ if current_adapter?(:PostgreSQLAdapter)
Developer.connection.close
end
- threads.each { |t| t.join }
+ threads.each(&:join)
end
assert_equal original_salary, Developer.find(1).salary