在Rails中的事务中包装所有控制器操作

时间:2011-12-14 16:02:47

标签: sql ruby-on-rails ruby transactions

是否可以设置一个Rails应用程序,以便所有控制器操作都自动用事务包装,如果出现无法解决的异常,该事务会自动回滚?

我正在开发一个Rails 3应用程序,目前用于进行大量数据库更改的相当棘手的操作。而且我经常弄错了很多次!过了一会儿,我意识到我的代码没有工作,因为我的数据库中的数据不一致。

我可以很容易地用事务包装它(这是一个需要一个明确的实例!)。然而,它让我想到,至少在开发过程中,将这个想法应用于每个控制器动作都是有用的。

假设有可能,这有什么缺点吗?

2 个答案:

答案 0 :(得分:17)

有关信息,我在应用程序控制器中使用around_filter执行了此操作:

around_filter :wrap_in_transaction

def wrap_in_transaction
  ActiveRecord::Base.transaction do
    yield
  end
end

这只会在任何未处理的异常上回滚事务,并重新引发异常。

答案 1 :(得分:5)

可以吗?大概。 它应该完成吗?可能不是,否则这将是铁轨的一部分,或者已经有一个伟大的宝石。

如果您有特殊的复杂控制器操作正在执行大量的db活动,并且您希望它们处于事务中,我的建议是将此业务逻辑和持久性转换为模型方法,并将您的事务放在那里。这也使您可以更好地控制您可能并不总是希望这种情况发生的情况。

如果你真的,真的想要这样做,我敢打赌你可以用Rack中间件来做,就像这个(未经测试的)https://gist.github.com/1477287

# make this class in lib/transactional_requests.rb, and load it on start
require 'activerecord'

class TransactionalRequests
  def initialize(app)
    @app = app
  end

  def call(env)
    ActiveRecord::Base.transaction do
      @app.call(env)
    end
  end
end

# and in the app config
config.middleware.use "TransactionalRequest"