Ruby on 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

注意:这是对

由于不在本问题范围内的原因(请参见上面的注释),我希望能够启动Rails数据库事务,然后在不同的范围内回滚该事务。例如:

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:无法在事务中启动事务:开始事务
。可能有一个解决方法,但不是数据库不可知的方法。