[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

#respond_to? not working for dynamically generated methods

Maurice Gladwell

5/30/2007 8:42:00 AM

It seems Object#respond_to doesn't work for dynamically generated
methods:

SomeRailsModel.respond_to? 'find_by_name' #=> false

1. Is there some way to *really* check if an object will respond to a
message, even if it will respond by a dynamically generated method?

Right now, Object#respond_to? just doesn't do what it name promises: it
doesn't check if an object responds to a message :foo, only if the
object has a :foo method defined.

Thanks,
Maurice B. Gladwell

--
Posted via http://www.ruby-....

36 Answers

Stefano Crocco

5/30/2007 9:02:00 AM

0

Alle mercoledì 30 maggio 2007, Maurice Gladwell ha scritto:
> It seems Object#respond_to doesn't work for dynamically generated
> methods:
>
> SomeRailsModel.respond_to? 'find_by_name' #=> false
>
> 1. Is there some way to *really* check if an object will respond to a
> message, even if it will respond by a dynamically generated method?
>
> Right now, Object#respond_to? just doesn't do what it name promises: it
> doesn't check if an object responds to a message :foo, only if the
> object has a :foo method defined.
>
> Thanks,
> Maurice B. Gladwell

Are you sure find_by_name is a class method and not an instance method (i.e,
do you call SomeRailsModel.find_by_name or something like
SomeRailsModel.new.find_by_name)? I don't know Rails, so I may be wrong, but
to me it seems that find_by_name is an instance method. If it is so, then you
can't expect SomeRailsModel.respond_to? to return true. This has nothing to
do with the method being dynamically generated. For instance,

Array.respond_to?(:select)

gives false, because select is an instance method.

Array.new.respond_to?(:select)

gives true, instead.

If you want to know whether a class has an *instance* method without first
creating an instance of the class, you can call instance_methods on the
class. It will return an array with the names of the methods instances of the
class will have. For example:

Array.instance_methods
=>["select", "[]=", "inspect", "<<", ... ]

In your case, if find_by_name is an instance method, you can do this:

SomeRailsModel.instance_methods.include? 'find_by_name'

I hope this helps

Stefano

Maurice Gladwell

5/30/2007 9:10:00 AM

0

Stefano Crocco wrote:
> Are you sure find_by_name is a class method and not an instance method

Yes, I'm positive:

>> SomeRailsModel.respond_to? 'find_by_name'
=> false

>> SomeRailsModel.find_by_name 'foo'
=> #<SomeRailsModel:@name='foo'>

M.

--
Posted via http://www.ruby-....

Nobuyoshi Nakada

5/30/2007 9:12:00 AM

0

Hi,

At Wed, 30 May 2007 18:01:59 +0900,
Stefano Crocco wrote in [ruby-talk:253530]:
> In your case, if find_by_name is an instance method, you can do this:
>
> SomeRailsModel.instance_methods.include? 'find_by_name'

method_defined? would be better in almost cases.

--
Nobu Nakada

Sascha Abel

5/30/2007 10:04:00 AM

0

Maurice Gladwell wrote:
> It seems Object#respond_to doesn't work for dynamically generated
> methods:
>
> SomeRailsModel.respond_to? 'find_by_name' #=> false
>
> 1. Is there some way to *really* check if an object will respond to a
> message, even if it will respond by a dynamically generated method?
>
> Right now, Object#respond_to? just doesn't do what it name promises: it
> doesn't check if an object responds to a message :foo, only if the
> object has a :foo method defined.
>
> Thanks,
> Maurice B. Gladwell

I think 'Object#respond_to?' just looks at a list of previously
*defined* methods, as does 'method_defined?', it doesn't matter if
they're defined dynamically at runtime or not. 'find_by_name' is not
really a method in Rails, it's just the magic of method_missing that you
can call it on SomeRailsModel.

In order to find out which methods SomeRailsModel would respond to you'd
have to write a method that looks at 'method_missing' and works out all
the possibilities there. I'm by no means an expert (neither for Ruby nor
Rails), but SomeRailsModel will respond to every 'find_by_foo' method,
where foo is column of the underlying database, so your task seems way
too big for such like me..

Sascha

--
Posted via http://www.ruby-....

dblack

5/30/2007 10:38:00 AM

0

Daniel DeLorme

5/30/2007 11:08:00 AM

0

dblack@wobblini.net wrote:
> Basically, to know what's going to happen dynamically, you have to run
> the program and send the messages.

Or you have to patch rails so that respond_to? will take this case into
account. It's open source, what are you waiting for? ;-)

Daniel

Robert Dober

5/30/2007 11:51:00 AM

0

On 5/30/07, dblack@wobblini.net <dblack@wobblini.net> wrote:
> Hi --
>
> On Wed, 30 May 2007, Maurice Gladwell wrote:
>
> > It seems Object#respond_to doesn't work for dynamically generated
> > methods:
> >
> > SomeRailsModel.respond_to? 'find_by_name' #=> false
> >
> > 1. Is there some way to *really* check if an object will respond to a
> > message, even if it will respond by a dynamically generated method?
> >
> > Right now, Object#respond_to? just doesn't do what it name promises: it
> > doesn't check if an object responds to a message :foo, only if the
> > object has a :foo method defined.
Does not look right though

# vim: sts=2 sw=2 expandtab nu tw=0:


module M
def m; "m" end
end
class A
def a; "a" end
end

class B < A
include M
end

b = B.new
def b.b; "b" end

p B.new.respond_to?(:a)
p B.new.respond_to?(:m)
p B.method_defined?(:a)
p B.method_defined?(:m)
p b.respond_to?(:b)
true
true
true
true
true

looks pretty good to me.
Is Rails fooling around with my beloved Ruby ;) ?
For what concerns intercepted messages for which no methods exist
David has said it all below:...
>
> That's what responding to a method means. Otherwise, it would be
> meaningless, since you can send any message to any object.
>
> Things like find_by_name are made possible by method_missing, which
> intercepts uninterpretable messages. It's possible for method_missing
> to generate a new method dynamically, but it doesn't have to (and in
> fact "find_by_name" does not get generated as a method; it just gets
> examined as a string). Even if it does, there's no way for respond_to
> to figure it out.
>
> Basically, to know what's going to happen dynamically, you have to run
> the program and send the messages.
>
>
> David
>
> --
> Q. What is THE Ruby book for Rails developers?
> A. RUBY FOR RAILS by David A. Black (http://www.manning...)
> (See what readers are saying! http://www.r.../r...)
> Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
> A. Ruby Power and Light, LLC (http://www.r...)
>
>

Cheers
Robert
--
You see things; and you say Why?
But I dream things that never were; and I say Why not?
-- George Bernard Shaw

dblack

5/30/2007 11:56:00 AM

0

Maurice Gladwell

5/30/2007 11:56:00 AM

0

David wrote:
> [...]
> Basically, to know what's going to happen dynamically, you have to run
> the program and send the messages.

It would be possible to define at writing time the entire range of
messages that an object will respond to. Here's how:

There are two kinds of messages to which an object responds by something
that is not a NoMethodError:

1) Those corresponding to defined instance methods.

2) Those that are handled in some way by method_missing.

#1 is already well defined and thus handled by #respond_to?. So if we
could just define the range of messages recognized by method_missing, we
could have an object return the entire range of messages to which it
will respond.

Of course, we don't have standard support for that currently, but we
could (e.g. with some DSL) declare inside the class definition (e.g.
above the `def method_missing`) patterns to which method_missing would
respond.

So for example, in ActiveRecord::Base we would have something like:

responds_to /find_by_.+/

Thus `SomeRailsModel.respond_to? :find_by_name` would have the knowledge
it needs to return the correct answer: true.

--
M.

--
Posted via http://www.ruby-....

Robert Dober

5/30/2007 12:00:00 PM

0

On 5/30/07, dblack@wobblini.net <dblack@wobblini.net> wrote:

> > Is Rails fooling around with my beloved Ruby ;) ?
>
> No, it's just using method_missing, which intercepts the
> "find_by_name" message.
Ok that is acceptable ;) thx for the clarification.
>
> > For what concerns intercepted messages for which no methods exist
> > David has said it all below:...
>
> I'll go along with that :-)
We are risking recursive mutual agreement causing stack overflow ;)
Cheers
Robert


--
You see things; and you say Why?
But I dream things that never were; and I say Why not?
-- George Bernard Shaw