问题
Note: This is a follow up question to Optimising Rspec Tests to Avoid Repeating Complex Setup Proceedures
For reasons that are outside the scope of this question (see the note above), I want to be able to start a Rails database transaction and then rollback that transaction in a different scope. E.g:
def before_callback
start_transaction # Start the transaction
# Create/Update some records
end
def after_callback
rollback_transaction # Rollback changes from before_callback and do_stuff
end
def do_stuff
before_callback
# Do some stuff
after_callback
end
do_stuff
I realize this is a contrived example which could be resolved easily with transaction do .. end and a little refactoring, but in the context have in mind do_stuff is part of an external plugin that I really don't want to mess with. Is there a way to do something similar to what I just described in Rails?
回答1:
For a crude quick-and-dirty solution you could just execute the required SQL commands directly on the database connection:
def start_transaction
ActiveRecord::Base.connection.execute("BEGIN")
end
def rollback_transaction
ActiveRecord::Base.connection.execute("ROLLBACK")
end
Also looking at the source of the transaction method might give you some ideas on how to approach this in a more refined manner.
(You can find it in ActiveRecord::ConnectionAdapters::DatabaseStatements in lib/active_record/connection_adapters/abstract/database_statements.rb)
来源:https://stackoverflow.com/questions/12675128/rolling-back-transactions-without-using-a-block