Amol Pujari
Amol Pujari

Reputation: 2349

How to know object for which Ruby Exception was occured

I believe in most of the cases when exceptions occur, they do occur around an object, as a result of attempt to call a method on an object, or they occur while executing some code which is part of some method belonging to an object.

How I come to know this object from the given Exception instance?

Example

begin
  ....
rescue ActiveRecord::SerializationTypeMismatch => e
  object = e.some_method_which_will_return_active_record_object
rescue => e
  object = e.get_me_object_around_which_this_happened
end

In my particular case, I want to know for which AR object SerializationTypeMismatch occurred.

Am not interested in e.message or backtrace in this case, I also checked e.methods, but did not find the way out to know the associated object.

Upvotes: 1

Views: 171

Answers (1)

Stuart M
Stuart M

Reputation: 11588

I believe in most of the cases when exceptions occur, they do occur around an object, as a result of attempt to call a method on an object, or they occur while executing some code which is part of some method belonging to an object.

But that's not true in all cases, and in general there is no relationship between an Exception that is raised and an object "around which" it occurred, since there may not always be an object.

For instance, LoadError is raised when a required file (e.g. a Ruby script) fails to load. That doesn't really relate to any particular object instance. I don't believe the initializer methods for any of the standard exception classes accept an argument for storing the object related to that exception, so there isn't a direct way to map back to the originating object.

If you're unable to map back to the ActiveRecord object where the error is occurring, perhaps your begin/rescue block is placed "too high" in the stack of code being called. For instance, you may have something like this each loop in your begin block:

begin
  items.each do |item|
    raise RuntimeError unless item == "foo"
  end
rescue RuntimeError => e
  # which item caused the error?
end

In that scenario you have no way to know which item caused the error, but you could restructure your begin block to more directly wrap the code as follows:

items.each do |item|
  begin
    raise RuntimeError unless item == "foo"
  rescue RuntimeError => e
    # the object that raised the exception must be 'item'
  end
end

This is a contrived example of course, but hopefully it illustrates the technique of wrapping your begin/rescue block more closely around the code that may raise exceptions, so there is no ambiguity about which object is causing the problem.

Upvotes: 2

Related Questions