1

当涉及到不同错误的连续过滤时,Rescue 语句可以很好地发挥作用:

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

但是,当涉及到使用不同参数来挽救相同的错误时,这就是我在代码中使用的:

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

不用说,我不喜欢它。难道没有更聪明的方法来做到这一点吗?

4

2 回答 2

2

可能这不能回答你的问题,但在这种情况下,我会在调用它之前询问o它是否responds_to?是我想要调用的方法:

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
于 2013-06-13T18:50:46.620 回答
1
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')

输出:

Object does not respond to basic methods!
quux method called with [10, :hello, "world"]

这适用于没有#respond_to_missing?定义方法的对象,这很常见——我见过的大多数代码都#method_missing属于这一类。

于 2013-06-13T20:03:15.597 回答