How to tell if a method accepts this many arguments?

I have this bit of code:

m = board.method(cmd)
begin
    m.call(p, *args)
rescue ArgumentError => err
    p.notify "Too many arguments to command '#{cmd}'."
end

The “rescue ArgumentError” is meant to catch it if I tried to call the
method with too many arguments, because *args is user input that may
be invalid.

However, if m.call(p, *args) succeeds, but there’s a bug inside that
method that generates an ArgumentError, then the rescue also catches
it. (I don’t want to catch it; I want it to crash so that I’ll see
where the bug is. Dead Programs Tell No Lies.)

Would it be possible to:

  1. Check how many arguments the method wants without actually calling
    it,

or

  1. Make the rescue only apply to the m.call.

I don’t think #1 is possible; there is a Method#arity method, but if
the method takes a variable number of arguments, Method#arity only
tells me the minimum number of arguments, not the maximum number. For
example, take this function:

irb(main):004:0> def something(arg1, arg2, arg3=nil, arg4=nil); end
nil
irb(main):005:0> method(:something).arity
-3

This tells me the method needs at least 3 arguments. But it doesn’t
tell me that the method will not accept more than 4 arguments.

As for #2, I think I might be able to look at err.backtrace[0] and
make sure that it mentions the name of the method that I just called.
That seems like a dirty way of doing it, though (but I can’t think of
anything else).

Thinking more about this, wouldn’t it make more sense for Method#arity
to return a Range? e.g.:

def x(a, b) # arity is 2…2
def x(a, b, c = nil) # arity is 2…3
def x(a, b, *arr) # arity is 2…Infinity (yes, Ruby supports
# infinite ranges)

Then I could use the Range#=== operator to determine whether that’s
too many arguments. e.g.:

if the_method.arity === args.length
    the_method.call *args
else
    puts "Invalid number of arguments to command."
end
···

On Wed, Oct 16, 2002 at 09:27:09PM -0400, Philip Mak wrote:

there is a Method#arity method, but if the method takes a variable
number of arguments, Method#arity only tells me the minimum number
of arguments, not the maximum number.