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”会导致与循环的特定迭代相关的事务回滚,并在循环的下一个迭代的顶部恢复执行。相反,执行似乎在“做更多事情”行处恢复。就好像“下一个”语句被完全忽略了。我缺少什么?
在这种情况下,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正如我之前所说,使用该语句并不是最好的选择。