invalid_arity method similar to method missing ?

D

Didier Prophete

all,

Is there a function similar to method_missing when an existing method is
called with the wrong number of arguments ?

Suppose I have a class:
class MyClass
def my_func(var1, var2)
end
end

And then I end up calling:
MyClass.new.my_func

As expected, I end up getting an ArgumentError exception ('wrong number
of arguments...). Is there a way to catch these... something like a
'method_missing' (method_missing doesn't get called since the method
exists...), but which would work for wrong number of arguments.

-Didier

ps: obviously, for simple problems, I could end up using some default
argument values, but it won't work for the (real and more complex)
problem I am trying to solve...
 
L

Logan Capaldo

all,

Is there a function similar to method_missing when an existing
method is
called with the wrong number of arguments ?

Suppose I have a class:
class MyClass
def my_func(var1, var2)
end
end

And then I end up calling:
MyClass.new.my_func

As expected, I end up getting an ArgumentError exception ('wrong
number
of arguments...). Is there a way to catch these... something like a
'method_missing' (method_missing doesn't get called since the method
exists...), but which would work for wrong number of arguments.

-Didier

ps: obviously, for simple problems, I could end up using some default
argument values, but it won't work for the (real and more complex)
problem I am trying to solve...


you could let your function be called with any number of arguments
and then worry about it. Probably not what you were looking for though.

eg

def my_func(*args)
var1, var2 = *args
...
end
 
D

Didier Prophete

Hi Logan,

Thanks for your reply. Well, that doesn't solve my exact problem, but
it's something I'll keep in mind.

Here is actually what I am trying to do. I have these functions which
get their arguments from a 'request' object. Each argument is being
extracted one by one like this:

def f1
arg1 = requests[:arg1]
arg2 = requests[:arg2]
<do some work with arg1, arg2>
end

These functions are called by another class which populates the request
object (actually this is some rails code but the problem is not bound to
rails itself...). Now obviously, this is a little bit of a pain. It
would be much easier to simply write all these function like this, with
real parameters:

def f1(arg1, arg2)
<do some work with arg1, arg2>
end
(I am using f1, and arg1 and arg2, but actually you have more than one
of these functions and the number of arguments is variable...)

So my initial idea was to do something like:
if the caller class calls f1 with the wrong number of argument (zero
in my case):
look at the names of the parameters of the f1
extract value for these arguments from the request object
call f1 with the right parameters
end

Now it turns out that the caller class always uses 'send' to call f1, so
I don't quite need a generic 'invalid_arity' method anymore since I can
just check for the arity of the function being called right before using
'send'

But now my new problem is trying to get the argument names of a given
function. I haven't found a way to do that... I posted a msg on this
forum but didn't get any reply so far...

The best I can do is get a handle to the 'method' object. Something
like:
meth = self.method:)f1)

But I am stuck there... I would need something like:
meth.arg_list
which would return [ :arg1, :arg2 ], or something like that.

I am not even sure this is possible in ruby...

-Didier
 
L

Logan Capaldo

--Apple-Mail-4-330995758
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
charset=US-ASCII;
delsp=yes;
format=flowed


The best I can do is get a handle to the 'method' object. Something
like:
meth = self.method:)f1)

But I am stuck there... I would need something like:
meth.arg_list
which would return [ :arg1, :arg2 ], or something like that.

I don't believe there is a way to get the argument names from inside
ruby. Can you define these methods (f1 and friends) to take a hash
instead?

eg:
f1:)arg1 => 1, :arg2 => 2)

If you can't do this (you didn't write the functions) perhaps you
need a more robust abstraction, something like a class called
Invocation, or Call or something.

eg

class Call
attr_accessor :target, :method_name, :arguments
def argument_names
... # insert code here to list the names of the arguments
end
end

Of course you'll still need a way to generate this list. Perhaps with
RDoc. THis is a little complicated though, ideally you would simply
have the functions take a hash as its single parameter as I
mentioned. Still not quite sure what you are asking.
--Apple-Mail-4-330995758--
 
E

Eero Saynatkari

The best I can do is get a handle to the 'method' object. Something
like:
meth = self.method:)f1)

But I am stuck there... I would need something like:
meth.arg_list
which would return [ :arg1, :arg2 ], or something like that.

I don't believe there is a way to get the argument names from inside
ruby.

Slightly off-topic, but there is :)

def foo(a, b, c)
local_variables.each {|var| puts "#{var}: #{eval var}"}
end

foo 1, 2, 3
... Can you define these methods (f1 and friends) to take a hash
instead?

eg:
f1:)arg1 => 1, :arg2 => 2)

If you can't do this (you didn't write the functions) perhaps you
need a more robust abstraction, something like a class called
Invocation, or Call or something.

eg

class Call
attr_accessor :target, :method_name, :arguments
def argument_names
... # insert code here to list the names of the arguments
end
end

Of course you'll still need a way to generate this list. Perhaps with
RDoc. THis is a little complicated though, ideally you would simply
have the functions take a hash as its single parameter as I
mentioned. Still not quite sure what you are asking.


E
 
D

Didier Prophete

Logan,
I don't believe there is a way to get the argument names from inside
ruby.

yeah... I am afraid this is impossible in ruby...
Can you define these methods (f1 and friends) to take a hash
...
mentioned. Still not quite sure what you are asking.

ahah... well, thanks for helping me anyway. I really appreciate that.

Let me try to explain what my goal was:

Think about how controllers are handled in rails for a second. You end
up having methods after methods which are like:

def meth1
name = params[:name]
data = params[:data]
...
end

def meth2
arg1 = params[:arg1]
arg2 = params[:arg2]
arg3 = params[:arg3]
...
end

Well, this is a little tedious, so I wanted to instead declare these as:

def meth1(name, data)
...
end

def meth2(arg1, arg2, arg3)
...
end

(see how the arguments are passed to the methods rather than being
manually extracted from the 'params' object)

Well, it turns out that these controller methods are always called from
the same place, using:
send(action_name)
(where here, action_name is :meth1, or :meth2)

Now, in order to introduce my change and keep the framework working, I
would want to replace this little piece of code by something like:
arg_names = <figure out the argument names for the method I want to
call>
args = arg_names.map { |name| params[name] }
send(action_name, *args)

Or something like that. The idea being that the caller extracts the
parameter values from the 'params' object and invoke the appropriate
method with these parameters...

Now, because getting the argument names of a method might not be
possible in ruby, this whole thing will not work... But hey, thanks for
helping me (thank also to Eero for his slightly off-topic comment :)

-Didier
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,577
Members
45,052
Latest member
LucyCarper

Latest Threads

Top