How can I determine easily and programmatically whether a LocalJumpError arose from the caller’s immediate failure to supply a needed block to a method, or from deeper within that method and others it invokes?
By “easily,” I mean I’d like to avoid string inspection/regexen on $!.backtrace. A solution applicable to 1.8 and 1.9 is also preferred.
Motivation: When I botch a method call in ruby, it’s usually because I mistyped the method (NoMethodError), got the number of arguments wrong (ArgumentError) or neglected to pass a necessary block (LocalJumpError).
For a proxying or decorating wrapper object in ruby, I’d like to discriminate these caller or API errors from the implementor or environment errors that can raise the same classes of error. For example:
...
def method_missing(sym, *args, &block)
@wrapped.__send__(sym, *args, &block)
rescue NoMethodError
raise MyApp::BadInvocation, "duh - no such method" unless @wrapped.respond_to?(sym)
raise
rescue ArgumentError
raise MyApp::BadInvocation, "duh - wrong arg count" \
unless _args_fit_arity?(@wrapped.method(sym), args)
raise
rescue LocalJumpError
# XXX - what is the test?
raise
end
To find out whether the LocalJumpError was caused by the user forgetting to pass a block, you need to know two things: Whether the user supplied a block and whether the method needs a block. The first is easy: just check whether blk is nil. The second however is impossible (in plain ruby at least).
So I guess parsing the stack trace is your best bet.