Hello!
I experienced problems with testing transactions which are supposed to be
rolled back, but are not, because of transactional fixtures eliminating the
inner transaction. Can this be worked around somehow without turning off
transactional fixtures? Maybe savepoints can help this?
Does anyone have any experience with savepoints to achieve nested transaction
functionality? Both Postgres and MySQL support savepoints (didn''t check
others).
I was thinking to make a custom patch for AR to create savepoints for inner
transactions. Can somebody help me with achieving this (esp. with
connection_adapters and wrapping this all up as a plugin perhaps).
Something in the way of:
# Wrap a block in a transaction. Returns result of block.
def transaction(start_db_transaction = true)
transaction_open = false
savepoint_open = false
savepoint_name = nil
begin
if block_given?
if start_db_transaction
begin_db_transaction
transaction_open = true
else
savepoint_name = create_savepoint
savepoint_open = true
end
yield
end
rescue Exception => database_transaction_rollback
if transaction_open
transaction_open = false
rollback_db_transaction
end
if savepoint_open
savepoint_open = false
rollback_to_savepoint(savepoint_name)
end
raise
end
ensure
commit_db_transaction if transaction_open
release_savepoint(savepoint_name) if savepoint_open
end
Best regards,
Laas
You can use a database that support nested transactions. Pg and Oracle both do, I believe. -- -- Tom Mornini On Jun 15, 2006, at 8:14 AM, Laas Toom wrote:> Hello! > > I experienced problems with testing transactions which are supposed > to be > rolled back, but are not, because of transactional fixtures > eliminating the > inner transaction. Can this be worked around somehow without > turning off > transactional fixtures? Maybe savepoints can help this? > > Does anyone have any experience with savepoints to achieve nested > transaction > functionality? Both Postgres and MySQL support savepoints (didn''t > check > others). > > I was thinking to make a custom patch for AR to create savepoints > for inner > transactions. Can somebody help me with achieving this (esp. with > connection_adapters and wrapping this all up as a plugin perhaps). > > Something in the way of: > > # Wrap a block in a transaction. Returns result of block. > def transaction(start_db_transaction = true) > transaction_open = false > savepoint_open = false > savepoint_name = nil > begin > if block_given? > if start_db_transaction > begin_db_transaction > transaction_open = true > else > savepoint_name = create_savepoint > savepoint_open = true > end > yield > end > rescue Exception => database_transaction_rollback > if transaction_open > transaction_open = false > rollback_db_transaction > end > if savepoint_open > savepoint_open = false > rollback_to_savepoint(savepoint_name) > end > raise > end > ensure > commit_db_transaction if transaction_open > release_savepoint(savepoint_name) if savepoint_open > end > > > Best regards, > Laas > > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails
I do most of my testing with transactional fixtures, but where I need to
test a transaction itself, I create a separate test module like:
require File.dirname(__FILE__) + ''/../test_helper''
class MyTestNoTransFixturesTest < Test::Unit::TestCase
self.use_transactional_fixtures = false
fixtures :myfixture
def test01_my_test
# tests and assertions
end
end
Julian
--
Posted via http://www.ruby-forum.com/.
Hello! Instead of rewriting some of my tests to use non-transactional fixtures, I thought it would be more wise to patch AR insted. So I ended up writing a plugin, which now is availlable from: http://rubyforge.org/projects/arnesttransacts This plugin uses savepoints when one transaction has already been started and rolls back to/commits that savepoint instead. This is implemented by overlaying ActiveRecord::ConnectionAdapters::DatabaseStatements.transaction method and adding some helper methods to postgres and mysql adapters also. Currently only PostgreSQL is tested, though MySQL is also implemented, as it uses the same syntax, but I did not have time to test it with live database. It would be great if some Oracle, DB2 or Firebird users could implement this plugin for their database also. Comments and thougths are welcome. Best Regards, Laas Toom
This is very cool. Haven''t tried it yet, but I encourage you to submit this as a patch to the core team. -- -- Tom Mornini On Jun 20, 2006, at 8:24 AM, Laas Toom wrote:> Hello! > > Instead of rewriting some of my tests to use non-transactional > fixtures, I > thought it would be more wise to patch AR insted. So I ended up > writing a > plugin, which now is availlable from: > > http://rubyforge.org/projects/arnesttransacts > > This plugin uses savepoints when one transaction has already been > started and > rolls back to/commits that savepoint instead. This is implemented by > overlaying > ActiveRecord::ConnectionAdapters::DatabaseStatements.transaction > method and adding some helper methods to postgres and mysql > adapters also. > > Currently only PostgreSQL is tested, though MySQL is also > implemented, as it > uses the same syntax, but I did not have time to test it with live > database. > > It would be great if some Oracle, DB2 or Firebird users could > implement this > plugin for their database also. > > Comments and thougths are welcome. > > Best Regards, > Laas Toom > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails