Are there any things to be careful about when defining the method_missing
method in Ruby? I'm wondering whether there are some not-so-obvious interactions from inheritance, exception throwing, performance, or anything else.
A somewhat obvious one: always redefine respond_to?
if you redefine method_missing
. If method_missing(:sym)
works, respond_to?(:sym)
should always return true. There are many libraries that rely on this.
Later:
An example:
# Wrap a Foo; don't expose the internal guts. # Pass any method that starts with 'a' on to the # Foo. class FooWrapper def initialize(foo) @foo = foo end def some_method_that_doesnt_start_with_a 'bar' end def a_method_that_does_start_with_a 'baz' end def respond_to?(sym, include_private = false) pass_sym_to_foo?(sym) || super(sym, include_private) end def method_missing(sym, *args, &block) return foo.call(sym, *args, &block) if pass_sym_to_foo?(sym) super(sym, *args, &block) end private def pass_sym_to_foo?(sym) sym.to_s =~ /^a/ && @foo.respond_to?(sym) end end class Foo def argh 'argh' end def blech 'blech' end end w = FooWrapper.new(Foo.new) w.respond_to?(:some_method_that_doesnt_start_with_a) # => true w.some_method_that_doesnt_start_with_a # => 'bar' w.respond_to?(:a_method_that_does_start_with_a) # => true w.a_method_that_does_start_with_a # => 'baz' w.respond_to?(:argh) # => true w.argh # => 'argh' w.respond_to?(:blech) # => false w.blech # NoMethodError w.respond_to?(:glem!) # => false w.glem! # NoMethodError w.respond_to?(:apples?) w.apples? # NoMethodError
If your method missing method is only looking for certain method names, don't forget to call super if you haven't found what you're looking for, so that other method missings can do their thing.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With