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