为什么不在循环工作中的事务中的救援块内调用下一个?

时间:2014-07-18 19:57:29

标签: ruby-on-rails ruby activerecord transactions

我有一个这样的循环:

# Iterate a list of items
req_wf_list.each do |req_wf|
    # Begin a transaction
    ReqWf.transaction do # ReqWf is an ActiveRecord model class
        # Do some things
        # ...

        # 1. I want to be able to continue processing with the
        #    next iteration of the loop if there is an error here
        # 2. I also want to rollback the transaction associated with
        #    this particular iteration if I encounter an error
        begin
            # Do something that might return an error
        rescue
            # Do some error processing
            puts "Caught such and such error"

            # Don't complete transaction (rollback),
            # don't "do some more things",
            # proceed to next item in req_wf_list
            next
        end

        # Do some more things
        # Shouldn't make it here if there is an error but I do indeed make it here
        # ...

    # End transaction
    end

# End loop
end

现在,我希望在救援块中调用“next”会导致与循环的特定迭代相关联的事务回滚并且在循环的下一次迭代的顶部恢复执行。相反,执行似乎在“多做事”行中恢复。就好像完全忽略了“下一个”语句。我错过了什么?

1 个答案:

答案 0 :(得分:4)

在这种情况下,很可能接下来应用于事务,因此您处于嵌套循环情况。

这是解决问题可以采取的措施的一个例子

req_wf_list.each do |req_wf|
  catch :go_here do  #:missingyear acts as a label
    ReqWf.transaction do

      throw :go_here unless something  #break out of two loops

    end
  end #You end up here if :go_here is thrown
end

但总的来说,使用next并不是一个好习惯。你应该能够设置一个全局的开始..救援,并在其中包含所有条件,这样一旦你发现错误就不会执行任何其他操作。

<强>更新

我做了一些小测试,行为就像你期望的那样。

loop = [1,2,3]
loop.each do |value|
  puts "value => #{value}"
  ActiveRecord::Base.transaction do
    puts "Start transaction"
    begin
      raise 
    rescue 
      puts "ActiveRecord::StatementInvalid"
      next
    end
    puts "Should not get here!"
  end
end

输出如下:

value => 1
Start transaction
ActiveRecord::StatementInvalid

value => 2
Start transaction
ActiveRecord::StatementInvalid

value => 3
Start transaction
ActiveRecord::StatementInvalid

在调用next之前,您的代码中是否有其他错误?

在任何情况下,使用next语句都不是我之前所说的最佳选择。