为什么在循环内的事务内的救援块内调用 next 不起作用?

Dan*_*Dan 3 ruby activerecord transactions ruby-on-rails

我有一个这样的循环:

# 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
Run Code Online (Sandbox Code Playgroud)

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

Raf*_*fal 5

在这种情况下,next 最有可能适用于事务,因此您处于嵌套循环情况。

这是解决问题的示例

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
Run Code Online (Sandbox Code Playgroud)

但总的来说,使用 并不是一个好的做法next。您应该能够放置一个全局 begin..rescue 并将所有条件包含在其中,以便一旦发现错误就不会执行任何其他操作。

更新

我做了一些小测试,其行为正如您所期望的那样。

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
Run Code Online (Sandbox Code Playgroud)

输出如下:

value => 1
Start transaction
ActiveRecord::StatementInvalid

value => 2
Start transaction
ActiveRecord::StatementInvalid

value => 3
Start transaction
ActiveRecord::StatementInvalid
Run Code Online (Sandbox Code Playgroud)

next在调用之前,您的代码中是否可能存在另一个错误?

无论如何,next正如我之前所说,使用该语句并不是最好的选择。