Ruby on rails 在不使用块的情况下回滚事务
注意:这是对 由于不在本问题范围内的原因(请参见上面的注释),我希望能够启动Rails数据库事务,然后在不同的范围内回滚该事务。例如:Ruby on rails 在不使用块的情况下回滚事务,ruby-on-rails,activerecord,Ruby On Rails,Activerecord,注意:这是对 由于不在本问题范围内的原因(请参见上面的注释),我希望能够启动Rails数据库事务,然后在不同的范围内回滚该事务。例如: def before_callback start_transaction # Start the transaction # Create/Update some records end def after_callback rollback_transaction # Rollback changes from before_callback
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
我意识到这是一个人为的例子,可以通过
transaction do轻松解决。。结束
并进行一点重构,但在上下文中,记住,do_stuff
是一个外部插件的一部分,我真的不想弄乱它。有没有类似于我刚才在Rails中描述的方法?对于一个粗糙、快速、肮脏的解决方案,您可以直接在数据库连接上执行所需的SQL命令:
def start_transaction
ActiveRecord::Base.connection.execute("BEGIN")
end
def rollback_transaction
ActiveRecord::Base.connection.execute("ROLLBACK")
end
另外,查看事务方法的源代码可能会让您了解如何以更精确的方式处理此问题
(你可以在lib/active\u record/connection\u adapters/abstract/database\u statements.rb的ActiveRecord::ConnectionAdapters::DatabaseStatements
中找到它)这会不会“又快又脏”如果在start\u transaction
和end\u transaction
之间存在其他事务,则解决方案中断,这取决于数据库,但大多数引擎都支持它。不过,它们可能不一定会创建真正的嵌套事务。(也就是说,它们只是忽略内部命令)。只需将事务的第三种方法放在那里:def end_transaction ActiveRecord::Base.connection.execute(“COMMIT”)end
它不适用于sqlite3——您会得到sqlite3::SQLException:无法在事务中启动事务:开始事务
。可能有一个解决方法,但不是数据库不可知的方法。