Can I enforce arity on a block passed to a method?
Your @action
will be a Proc
instance and Proc
s have an arity
method so you can check how many arguments the block is supposed to have:
def perform(*args)
if args.size != @action.arity
raise WrongArity.new(args.size)
end
@action.call(*args)
end
That should take care of splatless blocks like { |a| ... }
and { |a,b| ... }
but things are a little more complicated with splats. If you have a block like { |*a| ... }
then @action.arity
will be -1 and { |a,*b| ... }
will give you an arity
of -2. A block with arity -1 can take any number of arguments (including none), a block with arity -2 needs at least one argument but can take more than that, and so on. A simple modification of splatless test should take care of the splatful blocks:
def perform(*args)
if @action.arity >= 0 && args.size != @action.arity
raise WrongArity.new(args.size)
elsif @action.arity < 0 && args.size < -(@action.arity + 1)
raise WrongArity.new(args.size)
end
@action.call(*args)
end