Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add rescue in each method inside a class

Tags:

ruby

class A
  def a_method
    #..
  end
end

class B < A
  def method_1
    # ...
    a_method
  end

   def method_2
    # ...
    a_method
  end

  # ...

  def method_n
    # ...
    a_method
  end
end

The a_method ocassionally throws an AException.

I want to rescue from that exception, like:

class B < A
  def method_1
    # ...
    a_method
  rescue AException => e
    p e.message
  end

  # ...
end

I want to rescue the same way in each methods inside class B (method_1, method_2, ..., method_n). I'm stuck on figuring out a nice and clean solution, that would not require to duplicate the rescue code block. Can you help me with that?

like image 542
maicher Avatar asked Sep 15 '16 09:09

maicher


4 Answers

How about to use a block:

class B < A
  def method_1
    # some code here which do not raised an exception
    with_rescue do
      # method which raised exception
      a_method
    end
  end

  def method_2
    with_rescue do
      # ...
      a_method
    end
  end

  private 

  def with_rescue
    yield
  rescue => e
    ...
  end
end
like image 130
Philidor Avatar answered Oct 08 '22 14:10

Philidor


If you want to always rescue the exception, you could just override a_method in B:

class B < A
  def a_method
    super
  rescue AException => e
    p e.message
  end

  # ...
end

In addition you might want to return a value (like nil or false) to indicate the failure.

like image 38
Stefan Avatar answered Oct 08 '22 12:10

Stefan


Like this, perhaps?

class B < A

  def method_1
    # ...
    safe_a_method
  end

  private

  def safe_a_method
    a_method
  rescue AException => e
    ...
  end
end
like image 44
Sergio Tulentsev Avatar answered Oct 08 '22 12:10

Sergio Tulentsev


You can wrap your methods using a Module like this. The benefit is that unlike the other solutions you can call your methods with their regular names and the methods themselves don't have to be changed. Just extend the class with the ErrorHandler method en at the end enumerate the methods to wrap them with your errorhandling logic.

module ErrorHandler
  def wrap(method)
    old = "_#{method}".to_sym
    alias_method old, method
    define_method method do |*args|
      begin
        send(old, *args)
      rescue => e
        puts "ERROR FROM ERRORHANDLER #{e.message}"
      end
    end
  end
end

class A
  extend ErrorHandler
  def a_method v
    "a_method gives #{v.length}"
  end
  (self.instance_methods - Object.methods).each {|method| wrap method}
end

class B < A
  extend ErrorHandler
  def method_1 v
    "method_1 gives #{v.length}"
  end
  (self.instance_methods - Object.methods).each {|method| wrap method}
end

puts A.new.a_method "aa" # a_method gives 2
puts A.new.a_method 1 # ERROR FROM ERRORHANDLER undefined method `length' for 1:Fixnum
puts B.new.method_1 1 # ERROR FROM ERRORHANDLER undefined method `length' for 1:Fixnum
like image 37
peter Avatar answered Oct 08 '22 13:10

peter