简体   繁体   English

红宝石救援区 - 只用一个命令回应

[英]ruby rescue block — respond with more than just one command

I'm running a script with an API that often times out. 我正在运行带有API的脚本,该脚本经常超时。 I'm using begin/rescue blocks to get it to redo when this happens, but want to log what is happening to the command line before I run the redo command. 当发生这种情况时,我正在使用begin/rescue块来redo它,但是在运行redo命令之前想要记录命令行中发生的事情。

begin
#...api query...
rescue ErrorClass
  puts("retrying #{id}") && redo
end

Unfortunately the above script doesn't work. 不幸的是,上面的脚本不起作用。 Only the first command is run. 仅运行第一个命令。

I would like to force the rescue block to run multiple lines of code like so: 我想强制救援块运行多行代码,如下所示:

begin
 # api query
rescue ErrorClass do ###or:# rescue ErrorClass do |e|
  puts "retrying #{id}"
  redo
 end

but those don't work either. 但那些也不起作用。

I've had luck creating a separate method to run like so: 我有幸运行创建一个单独的方法来运行:

def example
  id = 34314
  begin
    5/0
  rescue ZeroDivisionError
    eval(handle_zerodiv_error(id))
  end
end

def handle_zerodiv_error(id)
  puts "retrying #{id}"
  "redo"
end

...that actually works. ......实际上有效。 But it requires too many lines of code in my opinion and it uses eval which is not kosher by any means according to my mentor(s). 但是在我看来,它需要太多的代码行,并且根据我的导师使用eval,这并不是犹太人。

You are unnecessarily complicating things by using && or do . 使用&&do会使事情变得不必要。 The && version does not work because puts returns nil , so by shortcut evaluation of && , the part to follow is not evaluated. &&版本不起作用,因为puts返回nil ,因此通过&&的快捷方式评估,不评估要遵循的部分。 If you use || 如果你使用|| or ; ; instead, then it will work: 相反,它会工作:

begin
  ...
rescue ErrorClass
  puts("retrying #{id}") || redo
end

begin
  ...
rescue ErrorClass
  puts("retrying #{id}"); redo
end

but even this is not necessary. 但即使这样也没有必要。 You somehow seem to believe that you need a block within rescue to write multiple lines, but that does not make sense because you are not using a block with single line. 你似乎在某种程度上相信你需要一个rescue块来编写多行,但这没有意义,因为你没有使用单行的块。 There is no Ruby construction that requires a block only when you have multiple lines. 没有Ruby构造只有在有多行时才需要块。 So, just put them in multiple lines: 所以,只需将它们分成多行:

begin
  ...
rescue ErrorClass
  puts("retrying #{id}")
  redo
end

There is a retry built in. This example is from "The Ruby Programming Language" pg 162. 内置了retry 。这个例子来自“The Ruby Programming Language”第162页。

require  "open-uri"

tries = 0
begin
  tries +=1
  open("http://www.example.com/"){|f| puts f.readlines}
rescue OpenURI::HTTPError => e
  puts e.message
  if (tries < 4)
    sleep (2**tries)  # wait for 2, 4 or 8 seconds
    retry             # and try again
  end
end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM