0

I'm using method_missing to define a class for namespacing constants in a vocabulary. To be effective, I need the vocabulary class to inherit from BasicObject, otherwise none of the standard object methods are available as vocabulary terms (because the method isn't missing :). However, when I inherit from BasicObject, I find I can't call utility methods in another module. The following code illustrates the issue in condensed form:

module Foo
  class Bar
    def self.fubar( s )
      "#{s} has been fubar'd"
    end
  end
end

class V1
  def self.method_missing( name )
    Foo::Bar.fubar( "#{name} in v1" )
  end
end

class V2 < BasicObject
  def self.method_missing( name )
    Foo::Bar.fubar( "#{name} in v2" )
  end
end

# this works
puts V1.xyz
# => xyz in v1 has been fubar'd

# this doesn't
puts V2.xyz
# => NameError: uninitialized constant V2::Foo

What would I need to add to V2 so that it doesn't produce an unitialized constant error when I try to call the helper module?

Ian Dickinson
  • 12,875
  • 11
  • 40
  • 67

1 Answers1

3

It works if you change the method in V2 like this so that name resolution starts in the global scope.

def self.method_missing( name )
  ::Foo::Bar.fubar( "#{name} in v2" )
end

I looked it up in the documentation for you:

BasicObject does not include Kernel (for methods like puts) and BasicObject is outside of the namespace of the standard library so common classes will not be found without a using a full class path. ... Access to classes and modules from the Ruby standard library can be obtained in a BasicObject subclass by referencing the desired constant from the root like ::File or ::Enumerator.

Michael Kohl
  • 66,324
  • 14
  • 138
  • 158