Hi Matt/all,
Actually from what I can see Rails does not hold off on trigger it’s “after_save” callbacks until just before commit in the case they are wrapped in a specific transaction (unfortunately). So there’s still no “before_commit” equivalent yet anyone has identified. Let me know if I’m wrong however here’s the test I’ve run.
------------------- test output -------------------------------------------------
Macintosh-2:after_create_test greg$ spec spec/model/with_transaction_block.rb
BOOK: before_save
F
-
RuntimeError in ‘Book should allow creation of book-allocation-chapter if costs match’
amounts do NOT match
./spec/model/with_transaction_block.rb:27:in `after_save_check’
./spec/model/with_transaction_block.rb:57:
./spec/model/with_transaction_block.rb:56:
Finished in 0.048817 seconds
1 example, 1 failure
Macintosh-2:after_create_test greg$
--------------- spec ------------------------------------------------------------------
require File.expand_path(File.dirname(FILE) + ‘/…/spec_helper’)
------------ ALLOCATION -------------
class Allocation < ActiveRecord::Base
belongs_to :book
belongs_to :chapter
before_save :after_save_check
def after_save_check
puts "ALLOCATION: before_save"
b = self.book
sum = b.allocations.sum(:amount)
raise("amounts do NOT match") if !(b.amount == sum)
end
end
----------- BOOK ---------------
class Book < ActiveRecord::Base
has_many :allocations
has_many :chapters, :through => :allocations
before_save :after_save_check
def after_save_check
puts "BOOK: before_save"
sum = self.allocations.sum(:amount)
raise "amounts do NOT match" if !(self.amount == sum)
end
end
----------- CHAPTER ---------------
class Chapter < ActiveRecord::Base
has_many :allocations
has_many :books, :through => :allocations
before_save :after_save_check
def after_save_check
puts "CHAPTER: before_save"
end
end
--------- RSPEC (BOOK) ------------
describe Book do
before(:each) do
@b = Book.new(:amount => 100)
@c = Chapter.new()
end
it “should allow creation of book-allocation-chapter if costs match” do
Book.transaction do
@b.save! # SEEMS TO TRIGGER BOOK AFTER_SAVE HERE RATHER THAN HOLDING OFF
@c.save!
@a1 = Allocation.create!(:book_id => @[b.id](http://b.id), :chapter_id => @[c.id](http://c.id), :amount => 100)
end
end
end
-------mysql log -----------------------------------------------------------------
090125 15:31:46 1534 Connect root@localhost on after_create_test_test
1534 Query SET SQL_AUTO_IS_NULL=0
1534 Statistics
1534 Query SHOW FIELDS FROM books
1534 Query SHOW FIELDS FROM chapters
1534 Query BEGIN
1534 Query SHOW FIELDS FROM allocations
1534 Query SELECT sum(allocations
.amount) AS sum_amount FROM allocations
WHERE (allocations
.book_id = NULL)
1534 Query ROLLBACK
1534 Quit
Is my analysis correct?
Cheers
Greg