您是否可以将一个返回错误的代码块传递给方法?

时间:2016-11-14 22:01:04

标签: ruby methods error-handling nokogiri rescue

我经常发现自己正在处理这种情况:

require 'nokogiri'
require "open-uri"

url = "https://www.random_website.com/contains_info_I_want_to_parse"
nokodoc = Nokogiri::HTML(open(url))
# Let's say one of the following line breaks the ruby script
# because the element I'm searching doesn't contain an attribute.
a = nokodoc.search('#element-1').attribute('href').text
b = nokodoc.search('#element-2').attribute('href').text.gsub("a", "A")
c = nokodoc.search('#element-3 h1').attribute('style').text.strip

我将创建大约30个变量,所有这些变量都在页面中搜索不同的元素,我将在多个页面上循环该代码。但是,这些页面中的一些可能具有如此略微不同的布局,并且不会具有这些div中的一个。这将破坏我的代码(因为你不能在nil上调用.attribute或.gsub)。但我永远无法猜到前一条线。 我的解决方案通常是围绕每一行:

begin
  line #n
rescue
  puts "line #n caused an error"
end

我希望能够做到这样的事情:

url = "https://www.random_website.com/contains_info_I_want_to_parse"
nokodoc = Nokogiri::HTML(open(url))

catch_error(a, nokodoc.search('#element-1').attribute('href').text)
catch_error(b, nokodoc.search('#element-2').attribute('href').text.gsub("a", "A"))
catch_error(c, nokodoc.search('#element-3 h1').attribute('style').text.strip)

def catch_error(variable_name, code)
  begin
    variable_name = code
  rescue
    puts "Code in #{variable_name} caused an error"
  end
  variable_name
end

我知道放&在每种新方法运作之前:

nokodoc.search('#element-1')&.attribute('href')&.text

但我希望能够在终端中显示错误并使用'puts'来查看我的代码何时出错。

有可能吗?

1 个答案:

答案 0 :(得分:1)

您不能将code作为常规参数传递给方法,因为它会在传递给catch_error方法之前进行评估(并引发异常)。您可以将其作为块传递 - 类似于

a = catch_error('element_1 href text') do 
  nokodoc.search('#element-1').attribute('href').text
end

def catch_error(error_description)
  yield
rescue
  puts "#{error_description} caused an error"
end

请注意,您无法将a作为variable_name传递给该方法:在调用该方法之前,它尚未在任何地方定义,因此您将获得{\ n} { {1}}错误。即使您之前定义undefined local variable or method,它也无法正常工作。如果您的代码在不引发异常的情况下工作,则该方法将返回正确的值,但该值不会存储在方法范围之外的任何位置。如果存在异常,a将在方法之前具有variable_name之前的任何值(a,如果您在未设置的情况下定义它),那么您的错误消息将输出类似{{1}的内容}}。这就是我添加nil参数的原因。

如果您不想每次都指定错误说明,也可以尝试记录邮件和回溯。

Code in  caused an error

我在这里做了一个额外的更改:将文档作为参数传递,以便error_description可以轻松记录标识文档的内容,以防重要。