Can anyone explain `#respond_to_missing?`.
on 2013-01-04 03:46
Hi,
"respond_to_missing?" makes "respond_to?" fit for dynamic methods
defined by "method_missing".
Normally, an object wouldn't know if it can respond to a dynamic method
call:
#-----------------------
class A
def method_missing name, *args
if name == :say_hi
puts 'Hi there!'
else
raise NoMethodError
end
end
end
a = A.new
a.say_hi # "Hi there!"
puts a.respond_to? :say_hi # => false
#-----------------------
But if you define "respond_to_missing?", you can work around this
problem:
#-----------------------
class A
def method_missing name, *args
if name == :say_hi
puts 'Hi there!'
else
raise NoMethodError
end
end
def respond_to_missing? name, include_private
name == :say_hi
end
end
a = A.new
a.say_hi # "Hi there!"
puts a.respond_to? :say_hi # => true
#-----------------------
on 2013-01-05 11:47
On 1/4/13 3:14 AM, Intransition wrote: > Can anyone explain `#respond_to_missing?`. > The answer can be found at [1]. irb:0> class Bar irb:1> def method_missing name, *args irb:2> p args irb:2> end irb:1> irb:1* def respond_to? name, include_private = false irb:2> true irb:2> end irb:1> end => nil irb:0> Bar.new.respond_to? :does_not_exist => true irb:0> Bar.new.method :does_not_exist NameError: undefined method `does_not_exist' for class `Bar' from (irb):112:in `method' from (irb):112 from /Users/sz/.rvm/rubies/ruby-1.9.3-p362/bin/irb:16:in `<main>' irb:0> class Foo irb:1> def respond_to? *args; super; end irb:1> irb:1* def respond_to_missing? *args irb:2> true irb:2> end irb:1> end => nil irb:0> Foo.new.respond_to? :does_not_exist => true irb:0> Foo.new.method :does_not_exist => #<Method: Foo#does_not_exist> [1] http://stackoverflow.com/questions/13793060/respon...
on 2013-01-05 12:43
Thank you Jan and Sandor. That is basically what I thought, but I had recently become confused b/c of this: https://bugs.ruby-lang.org/issues/5759 If you read toward the bottom of this thread, there is a case that seems contradictory. I still don't get it.
on 2013-01-05 21:59
How is that contradictory? Are you sure you got the return values of respond_to_missing? right? Because I guess you want to return *true* for :to_ary? respond_to? first checks if the method is actually, physically there. If that's not the case, it checks for respond_to_missing? In your case both checks return "false", so you end up with "false" just like you should.
on 2013-01-06 10:32
On Saturday, January 5, 2013 4:00:02 PM UTC-5, Jan E. wrote: > > Yes, that is what it should do. But notice #flatten doesn't seem to notice that it returns false. It still calls #to_ary on it, class Baz def method_missing(s); s; end def respond_to_missing?(s, x) return false if s == :to_ary true end end [Baz.new].flatten => in `flatten': can't convert Baz to Array (Baz#to_ary gives Symbol) (TypeError) Even though it appears to work fine if one overrides #respond_to? directly. class Baz def method_missing(s); s; end def respond_to?(s, x) super unless s == :to_ary end end [Baz.new].flatten => [#<Baz:0x007f8d3115c7d0>]
on 2013-01-06 12:41
On 1/5/13 12:42 PM, Intransition wrote: > Thank you Jan and Sandor. That is basically what I thought, but I had > recently become confused b/c of this: > > https://bugs.ruby-lang.org/issues/5759 > > If you read toward the bottom of this thread, there is a case that seems > contradictory. I still don't get it. > The difference of respond_to? and respond_to_missing? is that you can get a Method object using Kernel#method(sym) if a method will be dynamically implemented using method_missing. Here again the example: 13 class Bar1 14 def respond_to_missing? *args 15 true 16 end 17 def method_missing(*args, &blk) 18 p args 19 end 20 end 21 22 class Baz1 23 def respond_to? *args 24 true 25 end 26 27 def method_missing(*args, &blk) 28 p args 29 end 30 end # get the method: irb:0> Bar1.new.method :foo => #<Method: Bar1#foo> # do not get the method: irb:0> Baz1.new.method :foo NameError: undefined method `foo' for class `Baz1' from (irb):17:in `method' from (irb):17 from /.../.rvm/rubies/ruby-1.9.3-p362/bin/irb:16:in `<main>' In your example you define: "#to_ary() is not created dynamically nor defined static" class TransBaz1 def method_missing(s) s end def respond_to_missing?(s, x) return false if s == :to_ary true end end irb:0> TransBaz1.new.method :to_ary NameError: undefined method `to_ary' for class `TransBaz1' from (irb):45:in `method' from (irb):45 from /.../.rvm/rubies/ruby-1.9.3-p362/bin/irb:16:in `<main>' irb:0> TransBaz1.new.method :foo => #<Method: TransBaz1#foo> You can not get Method object :to_ary using Kernel#method, but you can get :foo.
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.