2012-07-13 64 views
1

我有一系列记录作为交易的一部分进行保存。除了正常的AR记录之外,我正在进行信用卡网关交易。如果它或AR交易失败,我希望一切回滚......除了从信用卡网关获取的失败交易(原因,日期等)的数据外。就像Rails在事务回滚时保存事务内的记录吗?

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 

有没有办法排除事务中的特定部分回滚失败?

的Rails 3.2.5,MySQL 5.1中

回答

7

我不是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)

另一个可能的策略是使用一个事实,即交易完成每一个连接的基础。两个线程将使用不同的连接,所以你可以这样做

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

这里的购买发生在另一个线程上,即使用自己的数据库连接。在该线程中发生的任何事情都不会回滚

+0

Doh!是的,在交易之外保存cc结果可能是我想要的。有时,明显的答案对我来说并不明显。线程技巧是整洁的;我看到了关于多个连接的文档中的警告,但没有做出飞跃来利用这个优势......虽然有点冒险,因为它似乎是实现的人工制品而不是有意的机制。任何方式,真棒答案 - 谢谢。 – 2012-07-14 23:27:37

+0

有用!小的更正:结果将是一个死的线程。要得到结果: result = nil Thread.new(result)do | result | ActiveRecord :: Base.connection_pool.with_connection do result = credit_card.purchase end end.join – 2015-07-13 22:56:07