Search code examples
ruby-on-railsrubyoptimizationrescue

How to handle exceptions in own method


How can I handle exceptions in its own method instead of this?

items.each do |item|
  begin
    url = item.url
    page = Nokogiri::HTML(open(url).read)
  rescue Exception => e
    puts "Couldn't read \"#{ url }\": #{ e }"
  else
    title = get_title(page)
  end
end

Something like:

def get_page(url)
  begin
    Nokogiri::HTML(open(url).read)
  rescue Exception => e
    puts "Couldn't read \"#{ url }\": #{ e }"
  end
end

#and then call:

items.each do |item|
 get_page(url)
 title = get_title(page)
end

Where should I place the else clause?


Solution

  • To start, you almost never want to rescue from Exception. Instead rescue from StandardError (or the specific errors). Exception is an ancestor of StandardError and includes errors that are most likely not recoverable (out of memory error, syntax error, for example).

    You can use

    rescue => e
    

    to rescue from standard error or

    rescue StandardError => e
    

    Any type of Nokogiri parsing error should inherit from StandardError. Net/HTTP is a little more problematic. See "What’s the best way to handle exceptions from Net::HTTP?", but you can just rescue them individually.

    Now to your question. You could return nil from your get_page method and check to see if the result of get_page is nil before getting the title:

    def get_page(url)
      Nokogiri::HTML(open(url).read)
    rescue => e
      puts "Couldn't read \"#{ url }\": #{ e }"
      nil
    end
    
    items.each do |item|
      url = item.url
      page = get_page(url)
    
      if page
        title = get_title(page)
      end
    end