Forum: Ruby Why doesn't method_missing affect respond_to?

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.
42172acdf3c6046f84d644cb0b94642c?d=identicon&s=25 Pat Maddox (pergesu)
on 2006-06-05 13:41
(Received via mailing list)
Take this class:

class Foo
  def method_missing(m, *args)
    m.to_s
  end
end

irb(main):006:0> Foo.new.foo
=> "foo"
irb(main):007:0> Foo.respond_to? :foo
=> false

This obviously just returns the name of any method that doesn't exist
for the object.  So if you can send the object any message and get a
result, why doesn't it respond_to those messages?

Pat
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2006-06-05 13:54
(Received via mailing list)
Hi --

On Mon, 5 Jun 2006, Pat Maddox wrote:

> irb(main):007:0> Foo.respond_to? :foo
> => false
>
> This obviously just returns the name of any method that doesn't exist
> for the object.  So if you can send the object any message and get a
> result, why doesn't it respond_to those messages?

Maybe because that would render #respond_to? essentially useless :-)


David
1b5341b64f7ce0244366eae17f06c801?d=identicon&s=25 Kirk Haines (Guest)
on 2006-06-05 14:21
(Received via mailing list)
On Monday 05 June 2006 5:39 am, Pat Maddox wrote:

> This obviously just returns the name of any method that doesn't exist
> for the object.  So if you can send the object any message and get a
> result, why doesn't it respond_to those messages?

Think about it from an implementation perspective.  How is respond_to?
to know
what method_missing is going to do?

If you define a method_missing method, and you need your object's
respond_to?
to reflect your method_missing magic, it is up to you to write a
respond_to
method that will do so.


Kirk Haines
B33ea5c12d767bfd1253940a960274f5?d=identicon&s=25 Tim Hunter (timhunter)
on 2006-06-05 14:23
Pat Maddox wrote:
> Take this class:
>
> class Foo
>   def method_missing(m, *args)
>     m.to_s
>   end
> end
>
> irb(main):006:0> Foo.new.foo
> => "foo"
> irb(main):007:0> Foo.respond_to? :foo
> => false
>
> This obviously just returns the name of any method that doesn't exist
> for the object.  So if you can send the object any message and get a
> result, why doesn't it respond_to those messages?
>
> Pat

The respond_to method can't know what method_missing is doing with
missing methods, so it's the up to the class author to provide a version
of respond_to that agrees with method_missing.
Ef3aa7f7e577ea8cd620462724ddf73b?d=identicon&s=25 Rob Biedenharn (Guest)
on 2006-06-05 16:01
(Received via mailing list)
On Jun 5, 2006, at 8:23 AM, Tim Hunter wrote:

>> => "foo"
> missing methods, so it's the up to the class author to provide a
> version
> of respond_to that agrees with method_missing.

More to the point, if you do this:
# foo.rb
class Foo
   def method_missing(m, *args)
     eval "def self.#{m}; '#{m}'; end"
     self.__send__(m)
   end
end

__END__

irb(main):001:0> require 'foo'
=> true
irb(main):002:0> f = Foo.new
=> #<Foo:0x1cd438>
irb(main):003:0> f.respond_to? :foo
=> false
irb(main):004:0> f.foo
=> "foo"
irb(main):005:0> f.respond_to? :foo
=> true
irb(main):006:0>

You've now defined a 'foo' method and further invocations of f.foo
will go to the newly minted method rather than method_missing each time.

-Rob
42172acdf3c6046f84d644cb0b94642c?d=identicon&s=25 Pat Maddox (pergesu)
on 2006-06-05 18:02
(Received via mailing list)
On 6/5/06, dblack@wobblini.net <dblack@wobblini.net> wrote:
> > end
> Maybe because that would render #respond_to? essentially useless :-)
>
>

In my example where the object responds to everything, sure.  It was
just an example though, and of course not every class is going to act
like this.

I guess the key is to write a predicate and stick it in both methods.

class Foo
 def method_missing(m, *args)
   valid_method?(m) ? m.to_s : super
 end

 def respond_to?(m)
  valid_method?(m)
 end

 private
 def valid_method?(m)
  true
 end
end

Of course it's not particularly useful here, but you could change
valid_method? to
def valid_method?(m)
  [ :foo, :bar ].include? m
 end

Guess I just thought Ruby would automatically pick it up.  However, I
don't see how it'd be able to, short of creating a copy of the object
in memory and calling the method on the object to see if it returns a
result.  If the copy gives a method missing error, then respond_to?
would return false.  Obviously it would suck to create a copy and
actually call the method just to see if an object responds to it.

Pat
B33ea5c12d767bfd1253940a960274f5?d=identicon&s=25 Tim Hunter (timhunter)
on 2006-06-05 19:01
Pat Maddox wrote:
> Guess I just thought Ruby would automatically pick it up.  However, I
> don't see how it'd be able to, short of creating a copy of the object
> in memory and calling the method on the object to see if it returns a
> result.  If the copy gives a method missing error, then respond_to?
> would return false.  Obviously it would suck to create a copy and
> actually call the method just to see if an object responds to it.
>
> Pat

Not to mention the problems that could occur when Ruby tries calling a
method just to see if it works:

class War
   def start(type=:nuclear)
   ...
   end
end

war = War.new
war.respond_to? :start
This topic is locked and can not be replied to.