<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -108,7 +108,7 @@ module ActiveRecord
         result = true
         load_target if @owner.new_record?
 
-        @owner.transaction do
+        transaction do
           flatten_deeper(records).each do |record|
             raise_on_type_mismatch(record)
             add_record_to_target_with_callbacks(record) do |r|
@@ -123,6 +123,21 @@ module ActiveRecord
       alias_method :push, :&lt;&lt;
       alias_method :concat, :&lt;&lt;
 
+      # Starts a transaction in the association class's database connection.
+      #
+      #   class Author &lt; ActiveRecord::Base
+      #     has_many :books
+      #   end
+      #
+      #   Author.find(:first).books.transaction do
+      #     # same effect as calling Book.transaction
+      #   end
+      def transaction(*args)
+        @reflection.klass.transaction(*args) do
+          yield
+        end
+      end
+
       # Remove all records from this association
       def delete_all
         load_target
@@ -173,7 +188,7 @@ module ActiveRecord
         records = flatten_deeper(records)
         records.each { |record| raise_on_type_mismatch(record) }
         
-        @owner.transaction do
+        transaction do
           records.each { |record| callback(:before_remove, record) }
           
           old_records = records.reject {|r| r.new_record? }
@@ -200,7 +215,7 @@ module ActiveRecord
       end
       
       def destroy_all
-        @owner.transaction do
+        transaction do
           each { |record| record.destroy }
         end
 
@@ -292,7 +307,7 @@ module ActiveRecord
         other   = other_array.size &lt; 100 ? other_array : other_array.to_set
         current = @target.size &lt; 100 ? @target : @target.to_set
 
-        @owner.transaction do
+        transaction do
           delete(@target.select { |v| !other.include?(v) })
           concat(other_array.select { |v| !current.include?(v) })
         end</diff>
      <filename>activerecord/lib/active_record/associations/association_collection.rb</filename>
    </modified>
    <modified>
      <diff>@@ -9,14 +9,14 @@ module ActiveRecord
       alias_method :new, :build
 
       def create!(attrs = nil)
-        @reflection.klass.transaction do
+        transaction do
           self &lt;&lt; (object = attrs ? @reflection.klass.send(:with_scope, :create =&gt; attrs) { @reflection.create_association! } : @reflection.create_association!)
           object
         end
       end
 
       def create(attrs = nil)
-        @reflection.klass.transaction do
+        transaction do
           self &lt;&lt; (object = attrs ? @reflection.klass.send(:with_scope, :create =&gt; attrs) { @reflection.create_association } : @reflection.create_association)
           object
         end</diff>
      <filename>activerecord/lib/active_record/associations/has_many_through_association.rb</filename>
    </modified>
    <modified>
      <diff>@@ -738,4 +738,13 @@ class HasAndBelongsToManyAssociationsTest &lt; ActiveRecord::TestCase
     # Array#count in Ruby &gt;=1.8.7, which would raise an ArgumentError
     assert_nothing_raised { david.projects.count(:all, :conditions =&gt; '1=1') }
   end
+
+  uses_mocha 'mocking Post.transaction' do
+    def test_association_proxy_transaction_method_starts_transaction_in_association_class
+      Post.expects(:transaction)
+      Category.find(:first).posts.transaction do
+        # nothing
+      end
+    end
+  end
 end</diff>
      <filename>activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1071,4 +1071,13 @@ class HasManyAssociationsTest &lt; ActiveRecord::TestCase
     ActiveRecord::Base.store_full_sti_class = old
   end
 
+  uses_mocha 'mocking Comment.transaction' do
+    def test_association_proxy_transaction_method_starts_transaction_in_association_class
+      Comment.expects(:transaction)
+      Post.find(:first).comments.transaction do
+        # nothing
+      end
+    end
+  end
+
 end</diff>
      <filename>activerecord/test/cases/associations/has_many_associations_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -220,4 +220,13 @@ class HasManyThroughAssociationsTest &lt; ActiveRecord::TestCase
     assert_equal [posts(:welcome).id, posts(:authorless).id].sort, person.post_ids.sort
     assert !person.posts.loaded?
   end
+
+  uses_mocha 'mocking Tag.transaction' do
+    def test_association_proxy_transaction_method_starts_transaction_in_association_class
+      Tag.expects(:transaction)
+      Post.find(:first).tags.transaction do
+        # nothing
+      end
+    end
+  end
 end</diff>
      <filename>activerecord/test/cases/associations/has_many_through_associations_test.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>2e75bd0808f4dcac328b690aaad176cbfe96773e</id>
    </parent>
  </parents>
  <author>
    <name>Hongli Lai (Phusion)</name>
    <email>hongli@phusion.nl</email>
  </author>
  <url>http://github.com/rails/rails/commit/70b8ea4fa6f432919340345ae0d5af6aa8f87ec8</url>
  <id>70b8ea4fa6f432919340345ae0d5af6aa8f87ec8</id>
  <committed-date>2008-09-23T11:32:01-07:00</committed-date>
  <authored-date>2008-09-20T12:59:49-07:00</authored-date>
  <message>Make AssociationCollection start transactions in the correct database.

AssociationCollection now starts transactions by calling
AssociationCollection#transaction instead of @owner.transaction or
@reflection.klass.transaction.

Signed-off-by: Michael Koziarski &lt;michael@koziarski.com&gt;

[#1081 state:committed]</message>
  <tree>d23147412f49339d8671b9933ca0a5528f9313ca</tree>
  <committer>
    <name>Michael Koziarski</name>
    <email>michael@koziarski.com</email>
  </committer>
</commit>
