[英]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
方法您ModelA
和ModelB
类? 看起来像这样:
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.