I have a Ruby C extension; I call that class FooC defined in ext/foo/foo.c, in that file I have
void Init_foo(void)
{
VALUE cFoo = rb_const_get(rb_cObject, rb_intern("FooC"));
:
rb_define_const(cFoo, "BAR", 7);
:
That is included in the "Ruby part" of the extension in lib/foo.rb like
class FooC ; end
require 'foo/foo'
class Foo < FooC
class << self
def puts_bar
puts BAR
end
:
end
:
end
Unexpectedly, I get an error
NameError: uninitialized constant #<Class:Foo>::BAR
I was expecting that Ruby would not find BAR in the Foo namespace, but would then search FooC where it would find it. Strangely, if I use Foo::BAR or self::BAR, the error goes away, and a similar usage in a Foo instance method gives me no errors at all.
Anyone have an idea as to why I need this seemingly redundant qualification of constants in singleton methods?
[edit]
Following the interesting answer below, I confirm that this qualification is not needed in a proper class method:
class Foo < FooC
def self.puts_bar
# no NameError here
puts BAR
end
:
end
rather than a instance method of the eigenclass.
You are looking the constant up in the eigenclass of
Foo, not in theFooitself. Start with figuring out what’s what without any c bindings.And see how it works:
Constants are made visible within instance functions by looking up the class’ constants.
#<Class:Foo>in the error message you’ve got is explicitly pointing out to that.