2016-11-14 7 views
0

나는 종종 자신이 시나리오 이런 종류의 처리 찾기 :메서드에 오류를 반환하는 코드 블록을 전달할 수 있습니까?

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 중 하나가 없습니다. 이것은 내 코드를 깨뜨릴 것이다 (예를 들어 .attribute 나 .gsub를 nil에 호출 할 수 없기 때문이다). 그러나 전 어느 선을 추측 할 수 없습니다.

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 

내가 각각의 새로운 방법 전에 & 퍼팅 작동하는지 알고 : 내가 좋아하는 뭔가를 할 수 있도록하고 싶습니다

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

: 내 이동 - 해결책은 일반적으로 각 행을 둘러싸고 있습니다 :

하지만 내 코드에 오류가 발생하는 경우 터미널에 'puts'오류를 표시 할 수 있기를 원합니다.

가능합니까?

답변

1

catch_error 메서드에 전달되기 전에 평가되고 예외가 발생하기 때문에 메서드에 대한 일반적인 인수로 전달할 수 없습니다. 이 메소드를 호출하기 전에 아무 곳이나 정의되지 않은, 그래서 당신은 얻을 것이다 : 당신이 variable_name 같은 방법으로 a를 전달할 수 없습니다

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 

주 같은 것을 - 당신은 블록으로 전달할 수 undefined local variable or method 오류. a을 먼저 정의하더라도 올바르게 작동하지 않습니다. 예외를 발생시키지 않고 코드가 작동하면 메서드는 올바른 값을 반환하지만 값은 메서드 범위 외부의 아무 곳에도 저장되지 않습니다. 예외가있는 경우 variable_name은 방법 (nil 설정없이 정의한 경우) 이전에 a 값을 가지므로 오류 메시지는 Code in caused an error과 같이 출력됩니다. 그래서 error_description 매개 변수를 추가했습니다.

매번 오류 설명을 지정하지 않으려는 경우 메시지 및 백 추적을 로깅 할 수도 있습니다.

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

def catch_error(doc) 
    yield doc 
rescue => ex 
    puts doc.title # Or something else that identifies the document 
    puts ex.message 
    puts ex.backtrace.join("\n") 
end 

나는 여기에 하나의 추가 변경 한 : rescue 쉽게 중요 경우, 문서를 식별 뭔가를 기록 할 수 있도록 매개 변수로 문서를 전달합니다.