在嵌套模块中访问常量

时间:2013-10-21 05:48:11

标签: ruby ruby-2.0

我在嵌套模块中访问模块常量时遇到问题。这是代码:

outer.rb

require 'inner.rb'

module Outer
  BASE_DIR = "cache/"
end

inner.rb

module Outer
  module Inner
    puts BASE_DIR
  end
end

如果我在inner.rb中运行代码,我会收到以下错误:

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

我认为既然BASE_DIR在外部模块中声明也应该可以在内部模块中访问,而且似乎不是这种情况。

2 个答案:

答案 0 :(得分:2)

这是一个加载顺序的问题。将require替换为所需的实际代码会显示您的代码按以下顺序加载:

module Outer
  module Inner
    puts BASE_DIR
  end
end

module Outer
  BASE_DIR = "cache/"
end

现在很容易理解为什么那不起作用。正如错误消息所示,当您尝试访问常量时,不会定义常量。发生这种情况是因为方法定义中的每一段代码都将立即执行。但是,可以从方法中访问常量:

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

module Outer
  BASE_DIR = "cache/"
end

Outer::Inner.foo
# cache/

根据您的需要,有几种可能的解决方案:

  • 消除使用常量外部方法(可能不是一种选择)
  • 更改加载顺序(将require放在文件的末尾)
  • 将全局设置的存储委托给专用的类/模块

答案 1 :(得分:0)

不,红宝石不这样做。看看ruby用来解析名字的祖先链。

因此您必须使用Outer::BASE_DIR

here是关于ruby类系统和rails自动加载的很好的讨论。