Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

method_missing gotchas in Ruby

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.

like image 607
readonly Avatar asked Nov 14 '08 19:11

readonly


2 Answers

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 
like image 58
James A. Rosen Avatar answered Oct 06 '22 09:10

James A. Rosen


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.

like image 30
Andrew Grimm Avatar answered Oct 06 '22 09:10

Andrew Grimm