Misc #20279
closedIs the implementation of `respond_to_missing?` in BasicObject documentation correct?
Description
Considering the documentation here: https://ruby-doc.org/3.2.2/BasicObject.html
Introduced in: https://github.com/ruby/ruby/commit/3eb7d2b33e3f8555d81db5369eb6fb7100a91e63
I wondered if or super
is correct in respond_to_missing?
.
For example:
irb(main):001* class MyObjectSystem < BasicObject
irb(main):002* DELEGATE = [:puts, :p]
irb(main):003*
irb(main):004* def method_missing(name, *args, &block)
irb(main):005* return super unless DELEGATE.include? name
irb(main):006* ::Kernel.send(name, *args, &block)
irb(main):007* end
irb(main):008*
irb(main):009* public def respond_to_missing?(name, include_private = false)
irb(main):010* DELEGATE.include?(name) or super
irb(main):011* end
irb(main):012> end
=> :respond_to_missing?
irb(main):013> MyObjectSystem.new.respond_to_missing?(:foo)
(irb):5:in `method_missing': super: no superclass method `respond_to_missing?' for an instance of MyObjectSystem (NoMethodError)
from (irb):10:in `respond_to_missing?'
from (irb):13:in `<main>'
from <internal:kernel>:187:in `loop'
from /home/samuel/.gem/ruby/3.3.0/gems/irb-1.11.2/exe/irb:9:in `<top (required)>'
from /home/samuel/.gem/ruby/3.3.0/bin/irb:25:in `load'
from /home/samuel/.gem/ruby/3.3.0/bin/irb:25:in `<main>'
It looks wrong to me.
In addition, I'd like to know in what situations BasicObject
should define respond_to_missing?
- because I was under the impression it was called by method_missing
. Does BasicObject#method_missing
have this behaviour? Maybe we can improve the documentation cc @burdettelamar (Burdette Lamar)
Updated by ioquatix (Samuel Williams) 11 months ago
- Subject changed from `respond_to_missing?` in BasicObject documentation correct? to Is the implementation of `respond_to_missing?` in BasicObject documentation correct?
Updated by byroot (Jean Boussier) 11 months ago
because I was under the impression it was called by method_missing.
respond_to_missing?
isn't called by method_missing
but by Kernel#respond_to?
, and BasicObject
doesn't define respond_to?
.
If you want to implement a delegator that responds to respond_to?
, you need to copy the method over from Kernel
:
class Proxy < BasicObject
DELEGATE = [:puts, :p]
define_method(:respond_to?, ::Kernel.instance_method(:respond_to?))
private
define_method(:respond_to_missing?, ::Kernel.instance_method(:respond_to_missing?))
def method_missing(name, *args, &block)
return super unless DELEGATE.include? name
::Kernel.send(name, *args, &block)
end
def respond_to_missing?(name, include_private = false)
DELEGATE.include?(name) or super
end
end
proxy = Proxy.new
p proxy.respond_to?(:puts)
proxy.puts "Hello"
true
Hello
Updated by byroot (Jean Boussier) 11 months ago
So yes, the documentation is incorrect.
Updated by ioquatix (Samuel Williams) 11 months ago
Do you want to submit a PR? You already wrote most of the code... however:
define_method(:respond_to_missing?, ::Kernel.instance_method(:respond_to_missing?))
def respond_to_missing?(name, include_private = false)
DELEGATE.include?(name) or super
end
Won't these clobber each other?
Updated by byroot (Jean Boussier) 11 months ago
Won't these clobber each other?
Yeah, my bad. You either need to copy it in an included module, or just not copy it over and not call super
.
Updated by Anonymous 10 months ago
- Status changed from Open to Closed
Applied in changeset git|e127289632396f268099c9815a59bc7e7f13b3ec.
[Bug #20279] [DOC] Update for BasicObject
The current implementation raises on the call to super