Question

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?

Was it helpful?

Solution 2

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.

OTHER TIPS

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top