1

In the following, iteration over ['a', nil, 'c'] will fail at nil since you cannot do nil + 'd'. I would like to rescue that message, modify it, and pass it on to another method that stores the error.

number = 0
begin
  ['a', nil, 'c'].each_with_index do |entry, i|
    entry + 'd'
    number = i
  end
rescue => e
  e.message="#{e.message} (happened at entry: #{number})"
  store_exception(e)
end

The problem is, the method message= does not exists. How do I do it?

sawa
  • 165,429
  • 45
  • 277
  • 381
Niels Kristian
  • 8,661
  • 11
  • 59
  • 117
  • Possible duplicate of [How do I add information to an exception message in Ruby?](https://stackoverflow.com/questions/2823748/how-do-i-add-information-to-an-exception-message-in-ruby) – Nomas Prime May 10 '18 at 11:58

3 Answers3

3

You could create your custom Exception and use it as a proxy object

class ProxyException < StandardError; end

number = 0
begin
  ['a', nil, 'c'].each_with_index do |entry, i|
    entry + 'd'
    number = i
  end
rescue => e
  e = ProxyException.new "#{e.message} (happened at entry: #{number})"
  store_exception(e)
end
fl00r
  • 82,987
  • 33
  • 217
  • 237
  • The only problem here is that it changes class of the exception as well. – BroiSatse Nov 04 '14 at 13:12
  • @BroiSatse does OP want original Exception class? – fl00r Nov 04 '14 at 13:15
  • @fl004 - It is not stated in the question. However since wants to modify exception message instead of just logging it modified version it would suggest that store_exception method is doing sth more complicated with an exception. Using ProxyException will also modify the backtrace. – BroiSatse Nov 04 '14 at 13:24
  • @BroiSatse It is easy to see the class of `e` and create an execption or that class. And, unlike messages, backtrace can be modified; it is not a problem. – sawa Nov 04 '14 at 13:55
0

In general, you should not use exceptions for EXPECTED circumstances (ask yourself: Will my code work if I remove all exception handling code?). This is an expected circumstance which you can easily avoid by calling compact before passing the array to each_with_index:

['a', nil, 'c'].compact #=> ["a", "c"]
daremkd
  • 8,244
  • 6
  • 40
  • 66
  • 1
    Mixed feelings about this answer - it might not be expected behaviour at all, all OP asked for is a way for better logging message from the exception. Your answer might be correct on how to fix this issue, but the issue itself could be just an example and hence you are not targeting the question itself. – BroiSatse Nov 04 '14 at 13:08
0

Answer based on @fl00r answer, but slightly more 'fancy':

class ProxyException < BasicObject
  def initialize(exception, message=nil)
    @exception, @message = exception, message
  end

  def message
    @message || @exception.message
  end

  def method_missing(method_name, *args, &block)
    @exception.public_send(method_name, *args, &block)
  end
end

Then simply:

number = 0
begin
  ['a', nil, 'c'].each_with_index do |entry, i|
    entry + 'd'
    number = i
  end
rescue => e
  e = ProxyException.new e, "#{e.message} (happened at entry: #{number})"
  store_exception(e)
end

ProxyException is completely invisible as it delegates all the methods, including class and object_id to the exception object and hence it retain exception class and backtrace.

BroiSatse
  • 44,031
  • 8
  • 61
  • 86