5

トランザクションの一部として保存する一連のレコードがあります。通常の AR レコードに加えて、クレジット カード ゲートウェイ取引を行っています。それまたは AR トランザクションが失敗した場合、クレジット カード ゲートウェイから返される失敗したトランザクションのデータ (理由、日付など) を除いて、すべてをロールバックしたいと考えています。何かのようなもの

def pay
  Payment.transaction do
    payment.save
    other.save
    result = credit_card.purchase  # this does the gateway transaction, no database stuff
    if result.failure
      raise ActiveRecord::Rollback
      result.save  # this is the part I want to always save
    end
    another.save
  end
end

失敗時のロールバックからトランザクション内の特定の部分を除外する方法はありますか?

レール 3.2.5、MySQL 5.1

4

1 に答える 1

13

なぜあなたがこれをしたいのか私は100%確信していませんが、あなたはあなたの取引の外でクレジットカードのものを保存することができますか?

result = nil
Payment.transaction do
  payment.save
  other.save
  result = credit_card.purchase  # this does the gateway transaction, no database stuff
  if result.failure
    raise ActiveRecord::Rollback      
  end
end
result.save

(ブロック変数のスコープがどのように機能するかにより、トランザクションの前に結果をnilに設定する必要があります)

別の可能な戦略は、トランザクションが接続ごとに行われるという事実を使用することです。2つのスレッドは異なる接続を使用するため、次のことができます。

Payment.transaction do
  payment.save
  other.save
  result = Thread.new do
    ActiveRecord::Base.connection_pool.with_connection do
      credit_card.purchase.tap do |result|
        result.save
      end
    end
  end.join.value
  if result.failure 
    raise ActiveRecord::Rollback
  end
end

または多分ちょうど:

Payment.transaction do
  payment.save
  other.save
  result = credit_card.purchase
  Thread.new do
    ActiveRecord::Base.connection_pool.with_connection do
      result.save
    end
  end.join
  if result.failure 
    raise ActiveRecord::Rollback
  end
end

ここでは、購入は別のスレッドで、つまり独自のデータベース接続で行われます。そのスレッドで発生したことはロールバックされません

于 2012-07-13T22:23:19.977 に答える