繁体   English   中英

使用ActiveRecord确保方法内的事务

[英]Ensuring a transaction within a method with ActiveRecord

我有一种情况,我想在事务中使用一种方法,但只有在事务尚未启动的情况下。 这是一个人为的例子来提炼我正在谈论的内容:

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! 如果模型方法是自己调用的,那么它们应该开始自己的事务,但是如果它们已经在事务中被调用,那么就像通过ConductBusinessLogic#process! ,他们不应该嵌套子交易。

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

有没有内置的方法来实现这种行为,如果没有,是否有一个宝石或补丁可以工作?

如何只添加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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM