From 999b7ed94d7d7f993cded7376fc4014128d43294 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper <jeremy@bitsweat.net>
Date: Wed, 5 Oct 2011 17:21:43 -0700
Subject: Transactional fixtures enlist all active database connections.

You can use multiple databases in your tests without disabling transactional fixtures.
---
 activerecord/CHANGELOG                             |  5 ++++
 activerecord/lib/active_record/fixtures.rb         | 24 ++++++++++++-----
 .../cases/adapters/sqlite3/sqlite3_adapter_test.rb |  4 +++
 activerecord/test/cases/fixtures_test.rb           | 30 +++++++++++++++++++---
 activerecord/test/cases/pooled_connections_test.rb |  2 ++
 activerecord/test/cases/primary_keys_test.rb       |  4 +++
 activerecord/test/cases/unconnected_test.rb        |  2 +-
 7 files changed, 61 insertions(+), 10 deletions(-)

(limited to 'activerecord')

diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG
index f974b5d237..10ad35ae3c 100644
--- a/activerecord/CHANGELOG
+++ b/activerecord/CHANGELOG
@@ -1,5 +1,10 @@
 *Rails 3.1.1 (unreleased)*
 
+* Transactional fixtures enlist all active database connections. You can test
+  models on different connections without disabling transactional fixtures.
+
+  [Jeremy Kemper]
+
 * Add deprecation for the preload_associations method. Fixes #3022.
 
   [Jon Leighton]
diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb
index 6f1ec7f9b3..cad9417216 100644
--- a/activerecord/lib/active_record/fixtures.rb
+++ b/activerecord/lib/active_record/fixtures.rb
@@ -842,9 +842,12 @@ module ActiveRecord
           @loaded_fixtures = load_fixtures
           @@already_loaded_fixtures[self.class] = @loaded_fixtures
         end
-        ActiveRecord::Base.connection.increment_open_transactions
-        ActiveRecord::Base.connection.transaction_joinable = false
-        ActiveRecord::Base.connection.begin_db_transaction
+        @fixture_connections = enlist_fixture_connections
+        @fixture_connections.each do |connection|
+          connection.increment_open_transactions
+          connection.transaction_joinable = false
+          connection.begin_db_transaction
+        end
       # Load fixtures for every test.
       else
         ActiveRecord::Fixtures.reset_cache
@@ -864,13 +867,22 @@ module ActiveRecord
       end
 
       # Rollback changes if a transaction is active.
-      if run_in_transaction? && ActiveRecord::Base.connection.open_transactions != 0
-        ActiveRecord::Base.connection.rollback_db_transaction
-        ActiveRecord::Base.connection.decrement_open_transactions
+      if run_in_transaction?
+        @fixture_connections.each do |connection|
+          if connection.open_transactions != 0
+            connection.rollback_db_transaction
+            connection.decrement_open_transactions
+          end
+        end
+        @fixture_connections.clear
       end
       ActiveRecord::Base.clear_active_connections!
     end
 
+    def enlist_fixture_connections
+      ActiveRecord::Base.connection_handler.connection_pools.values.map(&:connection)
+    end
+
     private
       def load_fixtures
         fixtures = ActiveRecord::Fixtures.create_fixtures(fixture_path, fixture_table_names, fixture_class_names)
diff --git a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
index 2b598220ee..eb6f071dc1 100644
--- a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
+++ b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
@@ -5,6 +5,8 @@ require 'models/owner'
 module ActiveRecord
   module ConnectionAdapters
     class SQLite3AdapterTest < ActiveRecord::TestCase
+      self.use_transactional_fixtures = false
+
       class DualEncoding < ActiveRecord::Base
       end
 
@@ -155,6 +157,8 @@ module ActiveRecord
         binary = DualEncoding.new :name => 'いただきます!', :data => str
         binary.save!
         assert_equal str, binary.data
+
+        DualEncoding.connection.drop_table('dual_encodings')
       end
 
       def test_execute
diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb
index 866dcefbab..1166c45843 100644
--- a/activerecord/test/cases/fixtures_test.rb
+++ b/activerecord/test/cases/fixtures_test.rb
@@ -451,14 +451,36 @@ end
 class CustomConnectionFixturesTest < ActiveRecord::TestCase
   set_fixture_class :courses => Course
   fixtures :courses
-  # Set to false to blow away fixtures cache and ensure our fixtures are loaded
-  # and thus takes into account our set_fixture_class
   self.use_transactional_fixtures = false
 
   def test_connection
     assert_kind_of Course, courses(:ruby)
     assert_equal Course.connection, courses(:ruby).connection
   end
+
+  def test_leaky_destroy
+    assert_nothing_raised { courses(:ruby) }
+    courses(:ruby).destroy
+  end
+
+  def test_it_twice_in_whatever_order_to_check_for_fixture_leakage
+    test_leaky_destroy
+  end
+end
+
+class TransactionalFixturesOnCustomConnectionTest < ActiveRecord::TestCase
+  set_fixture_class :courses => Course
+  fixtures :courses
+  self.use_transactional_fixtures = true
+
+  def test_leaky_destroy
+    assert_nothing_raised { courses(:ruby) }
+    courses(:ruby).destroy
+  end
+
+  def test_it_twice_in_whatever_order_to_check_for_fixture_leakage
+    test_leaky_destroy
+  end
 end
 
 class InvalidTableNameFixturesTest < ActiveRecord::TestCase
@@ -496,7 +518,9 @@ class ManyToManyFixturesWithClassDefined < ActiveRecord::TestCase
 end
 
 class FixturesBrokenRollbackTest < ActiveRecord::TestCase
-  def blank_setup; end
+  def blank_setup
+    @fixture_connections = [ActiveRecord::Base.connection]
+  end
   alias_method :ar_setup_fixtures, :setup_fixtures
   alias_method :setup_fixtures, :blank_setup
   alias_method :setup, :blank_setup
diff --git a/activerecord/test/cases/pooled_connections_test.rb b/activerecord/test/cases/pooled_connections_test.rb
index 379cf5b44e..434b8a677a 100644
--- a/activerecord/test/cases/pooled_connections_test.rb
+++ b/activerecord/test/cases/pooled_connections_test.rb
@@ -3,6 +3,8 @@ require "models/project"
 require "timeout"
 
 class PooledConnectionsTest < ActiveRecord::TestCase
+  self.use_transactional_fixtures = false
+
   def setup
     @per_test_teardown = []
     @connection = ActiveRecord::Base.remove_connection
diff --git a/activerecord/test/cases/primary_keys_test.rb b/activerecord/test/cases/primary_keys_test.rb
index 489c7d8310..4bb5752096 100644
--- a/activerecord/test/cases/primary_keys_test.rb
+++ b/activerecord/test/cases/primary_keys_test.rb
@@ -145,6 +145,10 @@ class PrimaryKeysTest < ActiveRecord::TestCase
     k.set_primary_key "bar"
     assert_equal k.connection.quote_column_name("bar"), k.quoted_primary_key
   end
+end
+
+class PrimaryKeyWithNoConnectionTest < ActiveRecord::TestCase
+  self.use_transactional_fixtures = false
 
   def test_set_primary_key_with_no_connection
     return skip("disconnect wipes in-memory db") if in_memory_db?
diff --git a/activerecord/test/cases/unconnected_test.rb b/activerecord/test/cases/unconnected_test.rb
index f85fb4e5da..e82ca3f93d 100644
--- a/activerecord/test/cases/unconnected_test.rb
+++ b/activerecord/test/cases/unconnected_test.rb
@@ -4,7 +4,7 @@ class TestRecord < ActiveRecord::Base
 end
 
 class TestUnconnectedAdapter < ActiveRecord::TestCase
-  self.use_transactional_fixtures = false unless supports_savepoints?
+  self.use_transactional_fixtures = false
 
   def setup
     @underlying = ActiveRecord::Base.connection
-- 
cgit v1.2.3