Reputation: 12578
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?
Upvotes: 1
Views: 1050
Reputation: 19230
Probably this don't answer your question, but in this case I'd ask to o
if it responds_to?
the method I want to call, before calling it:
method = [:foo, :bar, :baz].find { |m| o.respond_to?(m) }
if method
o.public_send(method)
else
warn "Object o responds not to basic methods!"
end
Upvotes: 2
Reputation: 1905
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.
Upvotes: 1