Forum: Ruby invalid_arity method similar to method missing ?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
B389820ea2e2ee4f166930dea947a303?d=identicon&s=25 Didier Prophete (didier-prophete)
on 2006-01-17 01:42
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...
E34b5cae57e0dd170114dba444e37852?d=identicon&s=25 Logan Capaldo (Guest)
on 2006-01-18 02:18
(Received via mailing list)
On Jan 16, 2006, at 7:06 PM, Didier Prophete wrote:

>     end
> -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...
>
> --
> Posted via http://www.ruby-forum.com/.
>


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
B389820ea2e2ee4f166930dea947a303?d=identicon&s=25 Didier Prophete (didier-prophete)
on 2006-01-18 03:06
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
E34b5cae57e0dd170114dba444e37852?d=identicon&s=25 Logan Capaldo (Guest)
on 2006-01-18 04:16
(Received via mailing list)
On Jan 17, 2006, at 8:30 PM, Didier Prophete wrote:

> 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.
5c7bdd14d6885c8275eaf78be41d120a?d=identicon&s=25 Eero Saynatkari (Guest)
on 2006-01-18 06:23
(Received via mailing list)
On 2006.01.18 11:40, Logan Capaldo wrote:
>
> 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

> eg
> have the functions take a hash as its single parameter as I
> mentioned. Still not quite sure what you are asking.


E
B389820ea2e2ee4f166930dea947a303?d=identicon&s=25 Didier Prophete (didier-prophete)
on 2006-01-20 10:40
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
This topic is locked and can not be replied to.