メソッドをトランザクション内で動作させたい状況がありますが、トランザクションがまだ開始されていない場合のみです。これは、私が話していることを要約するための不自然な例です。
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がこれをすぐに提供する方法を知りません。上記のコードをそのまま実行し、モデル メソッドの 1 つによってロールバックがトリガーされた場合、サブトランザクションがActiveRecord::Rollback
例外を飲み込むため、トランザクション全体が引き続き処理されます。サブトランザクションでオプションを使用するrequires_new
と、ネストされたトランザクションをシミュレートするためにセーブポイントが使用され、そのサブトランザクションのみが実際にロールバックされます。私が望む動作はActiveRecord::Base.ensure_transaction
、外部トランザクションがまだない場合にのみ新しいトランザクションが開始されるようにすることで、サブトランザクションが外部トランザクション全体のロールバックをトリガーできるようにすることです。これにより、これらのメソッドはそれ自体でトランザクション可能になりますが、親トランザクションがある場合はそれに従います。
この動作を実現する組み込みの方法はありますか?そうでない場合、機能するgemまたはパッチはありますか?