0

I'm having trouble accessing a module constant in a nested module. Here's the code:

outer.rb

require 'inner.rb'

module Outer
  BASE_DIR = "cache/"
end

inner.rb

module Outer
  module Inner
    puts BASE_DIR
  end
end

If I run the code in inner.rb I get the following error:

<module:Inner>': uninitialized constant Outer::Inner::BASE_DIR (NameError)

I thought that since BASE_DIR is declared in the outer module is should also be accessible in the inner module and it does not seem to be the case.

2
  • What's the error message at the top of your post? I took the freedom to delete it. Commented Oct 21, 2013 at 7:03
  • Bad copy/paste. Thanks for the edit. Commented Oct 21, 2013 at 14:29

2 Answers 2

2

It is a question of load order. Replacing the require with the actual code required reveals that your code is loaded in this order:

module Outer
  module Inner
    puts BASE_DIR
  end
end

module Outer
  BASE_DIR = "cache/"
end

Now it is pretty easy to see why that cannot work. As the error message suggests, the constant simply is not defined at the time when you try to access it. This happens because every piece of code that is not inside a method definition will be executed immediately. Accessing the constant from a method is however possible:

module Outer
  module Inner
    def self.foo
      puts BASE_DIR
    end
  end
end

module Outer
  BASE_DIR = "cache/"
end

Outer::Inner.foo
# cache/

There are several possible solutions, depending on your needs:

  • eliminate the use of the constant outside methods (may not be an option)
  • change load order (put the require at the end of the file)
  • Delegate the storage of global settings to a dedicated class/module
Sign up to request clarification or add additional context in comments.

Comments

0

no, ruby does not do that. have a look for the ancestor chain that ruby uses to resolve names.

so you will have to use Outer::BASE_DIR instead.

here is a nice talk about the ruby class system and rails auto loading.

2 Comments

Tried this as well. With puts Outer::BASE_DIR and getting this error (pretty much the same): <module:Inner>': uninitialized constant Outer::BASE_DIR (NameError)
have a look at the answer of @p11y that problem is related to the load order of files. ruby is sensitive to the order in which files and so ruby code is loaded.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.