Reputation: 33
I have the following 3 files:
test.rb
# doesn't work, raises error: NameError: uninitialized constant Baz
Foo::Bar.do_stuff_1
# does work
Foo::Bar.do_stuff_2
# does work
Foo::Bar.new.do_stuff_3
bar.rb
module Foo
class Bar
class << self
def do_stuff_1
puts "class level: #{Baz.new.class}"
end
end
def self.do_stuff_2
puts "class level: #{Baz.new.class}"
end
def do_stuff_3
puts "Instance level: #{Baz.new.class}"
end
end
end
baz.rb
module Foo
class Baz
def initialize
end
end
end
The do_stuff_1
method raises an exception, NameError: uninitialized constant Baz, while the other methods are executing normally. I think it has something to do with class << self ... end
adjusting the metaclass and def self.method ... end
adjusting the class itself.
I would like to know if there is way to make class << self ... end
autoload the Baz class appropriately like def self.method ... end
.
I'm using Rails 4.0.2, Ruby 2.0.0 and I'm autoloading the classes using application.rb.
Upvotes: 3
Views: 322
Reputation: 29419
This isn't an autoload problem per se, but rather a matter of namescopes. In the case of the first method, you're in the singleton class of Bar
, so you need to reference Baz
as Foo::Baz
.
If you wanted to reference Foo::Baz
from that context without using the name Foo
, you use any expression that evaluates to Foo
in that context, such as Module.nesting[2]
, as in:
puts "class level: #{Module.nesting[2]::Baz.new.class}"}
Upvotes: 1