1

create是一种方法,只有当所有事情按预期发生时才返回true,否则返回false。我正在寻找错误代码样式控制流程。返回内部交易和ActiveRecord ::回滚

class TransferOperator 
    class TransferError < Struct.new(:type, :message); ; end 

    attr_reader :transfer, :error 

    def initialize(transfer) 
    @transfer = transfer 
    end 

    # Creates the transfer and locks money in the bank 
    def create 
    return error(:validation_error) if transfer.invalid? 

    to_bank = transfer.main_to_bank 
    to_bank.with_lock do 
     # How does return here behave? Should a raise be issued instead and caught outside? 
     return error(:insufficient_buffer) if to_bank.available_balance < transfer.amount 
     to_bank.available_balance -= transfer.amount 
     to_bank.locked_balance += transfer.amount 
     to_bank.save! 
     transfer.save! 
    end 

    # Is it guaranteed here that the above transaction has always been succesful? 
    true 
    end 

    private 

    def error(type, message='') 
    @error = TransferError.new(type, message) 
    false 
    end 
end 

这里的想法是让呼叫者这样一个流程:

def move_money 
    @transfer = Transfer.new(params) 
    operator = TransferOperator.new(@transfer) 
    if operator.create 
    redirect_to :root, notice: 'success!' 
    else 
    if operator.error.type == :validation_error 
     render action: 'new' 
    elsif operator.error.type == :insufficient_buffer 
     redirect_to :root, notice: 'not enough money' 
    else 
     # Handle other errors here... 
    end 
    end 
end 

与事务中返回的错误会发生什么?

它保证交易成功,如果返回true?

http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html

一个例外是的ActiveRecord ::回滚异常,引发时将 触发回滚,而不是由 事务块重新提出。

有没有可能Rails自己提高ActiveRecord::Rollback?如果是这样,那么交易将默默地失败,并且真实地返回(这不是我们想要的)。

回答

2

如果要使事务回滚,则必须引发错误。您有几个选择:

  1. 提高ActiveRecord::Rollback并且事务将被回滚并且不会在事务块外重新生成错误。正如你所说,这将悄悄地回滚交易。可能不是你想要的。
  2. 引发任何其他类型的错误。这会导致事务回滚,并且会引发错误。您可以挽救该错误以适当地重定向用户。

返回一个错误对象什么也不做。这只是另一个传递的对象。

+0

我们可以指望Rails没有提高'ActiveRecord :: Rollback'本身_在事务处理? – randomguy 2014-10-06 22:25:51

+1

Rails永远不会引发一个'ActiveRecord :: Rollback'本身。那么,技术Rails内部使用这个错误,但它不会在你的事务块中引发它。 – infused 2014-10-06 22:27:38