Rescue statement serves well when it comes to successive filtering of different errors:
o = Object.new
begin
o.foo
rescue ArgumentError
puts "Object o does define #foo, but you got the argument number wrong!"
rescue NoMethodError
puts "Object o does not respond to #foo!"
else
puts "That's right!"
end
But when it comes to rescuing the same error with different parameters, this is what I use in my code:
o = Object.new
begin
o.foo
rescue NoMethodError
begin
o.bar
rescue NoMethodError
begin
o.quux
rescue NoMethodError
warn "Object o responds not to basic methods!"
end
end
end
Needless to say, I don't like it. Isn't there a more clever way to do this?
def send_messages_maybe(object, messages, *parameters)
object.send(messages.first, *parameters)
rescue NoMethodError
messages = messages[1..-1]
if messages.empty?
warn "Object does not respond to basic methods!"
else
retry
end
end
module Quux
def quux(*args)
puts "quux method called with #{args.inspect}"
end
end
messages = %i{foo bar quux}
send_messages_maybe(Object.new, messages)
send_messages_maybe(Object.new.extend(Quux), messages, 10, :hello, 'world')
Output:
Object does not respond to basic methods!
quux method called with [10, :hello, "world"]
This works with objects that don't have a #respond_to_missing?
method defined, which is very common --- most of the code I've seen that uses #method_missing
falls into this category.