6

我有一种情况,我想要一种在事务中工作的方法,但前提是事务尚未启动。这是一个人为的例子来提炼我在说什么:

class ConductBusinessLogic
  def initialize(params)
    @params = params
  end

  def process!
    ActiveRecord::Base.transaction do
      ModelA.create_multiple(params[:model_a])
      ModelB.create_multiple(params[:model_a])
    end
  end
end

class ModelA < ActiveRecord::Base
  def self.create_multiple(params)
    # I'd like the below to be more like "ensure_transaction"
    ActiveRecord::Base.transaction do
      params.each { |p| create(p) }
    end
  end
end

class ModelB < ActiveRecord::Base
  def self.create_multiple(params)
    # Again, a transaction here is only necessary if one has not already been started
    ActiveRecord::Base.transaction do
      params.each { |p| create(p) }
    end
  end
end

基本上,我不希望这些充当嵌套事务。我希望这些.create_multiple方法仅在尚未在事务中调用时才启动事务,例如通过ConductBusinessLogic#process!. 如果模型方法被自己调用,它们应该启动自己的事务,但如果它们已经在事务内部被调用,如 through ConductBusinessLogic#process!,它们不应该嵌套子事务。

我不知道 Rails 提供这种开箱即用的方式。如果我按原样运行上面的代码并且模型方法之一触发了回滚,那么整个事务仍然会通过,因为子事务会吞下ActiveRecord::Rollback异常。如果我使用requires_new在子事务上使用该选项,将使用保存点来模拟嵌套事务,并且实际上只有那个子事务会被回滚。我想要的行为会影响到ActiveRecord::Base.ensure_transaction,例如只有在没有外部事务时才启动新事务,以便任何子事务都可以触发整个外部事务的回滚。这将允许这些方法本身是事务性的,但如果有父事务,则遵从父事务。

是否有实现此行为的内置方法,如果没有,是否有可以工作的 gem 或补丁?

4

1 回答 1

2

给你的和类添加一个create_multiple_without_transaction方法怎么样?看起来像这样:ModelAModelB

class ConductBusinessLogic
  def initialize(params)
    @params = params
  end

  def process!
    ActiveRecord::Base.transaction do
      ModelA.create_multiple_without_transaction(params[:model_a])
      ModelB.create_multiple_without_transaction(params[:model_a])
    end
  end
end

class ModelA < ActiveRecord::Base
  def self.create_multiple(params)
    # I'd like the below to be more like "ensure_transaction"
    ActiveRecord::Base.transaction do
      self.create_multiple_without_transaction(params)
    end
  end

  def self.create_multiple_without_transaction(params)
    params.each { |p| create(p) }
  end
end

那么您的常规create_multiple将像以前一样工作,但是对于您不需要交易的情况,您只需致电create_multiple_without_transaction

于 2014-11-14T15:56:59.237 回答