类是必需的,但无法访问

Posted

技术标签:

【中文标题】类是必需的,但无法访问【英文标题】:Class is required but cannot be accessed 【发布时间】:2013-12-25 12:44:43 【问题描述】:

我有一个非常奇怪的错误,我无法理解。

基本上,我的lib 文件夹中有这个类:

# lib/api/amazon.rb
module API
  class Amazon
    ...
  end
end

当我想在某个地方使用它时,我require它:

require 'api/amazon'
API::Amazon.do_stuff

这最初是有效的,但过了一段时间它会中断并引发NameError: uninitialized constant API::Amazon。当我对此进行调试并在引发错误时再次尝试require该文件时,它返回false,表明该文件已经加载。我也可以在$"(这个加载文件列表)中看到它。为什么我不能访问API::Amazon

注意:我在ActiveSupport::Inflector 中添加了“API”作为首字母缩写词,这就是我不必使用“Api”的原因:

# config/initializers/inflections.rb
ActiveSupport::Inflector.inflections do |inflect|
  inflect.acronym 'API'
end

编辑:

我也试过::API::Amazon.do_stuff,结果一样。

【问题讨论】:

看起来ActiveSupport 不时对它的嵌套类进行一些清理,删除动态创建的。如果有人大量使用带有class_eval-like 方法的动态类扩展,则可能需要这样做。 不知道你的意思,@mudasobwa。我不使用任何动态 class_eval 的东西,它是一个没有任何动态或元编程魔法的常规课程。 你确实在已经存在的(和冻结的,根据their politics)模块下定义了一个类;说,你有猴子补丁ActiveSupport::InflectorActiveSupport,一旦加载,可能会对 它的嵌套类执行这样的清理。 我在config/initializers/inflections.rb 中以推荐的方式添加了首字母缩写词。我不认为这是问题 我猜你混淆了首字母缩写词:推荐的方法是添加首字母缩写词来教Inflector如何操作。例如,请参阅this post。您在他们的模块下添加了一个类。 【参考方案1】:

编辑:

虽然我找到了答案,但同样的错误又发生了...... :(

结束编辑

在@uncutstone 的帮助下,我似乎找到了答案。

原来我不仅为API::Amazon 使用了API 命名空间,还为一些控制器使用了命名空间,如下所示:

# app/controllers/api/v1/accounts_controller.rb
class API::V1::AccountsController < APIController
  ...
end

我的理论是这些控制器之一在某个时间点自动重新加载并重新初始化(因此清除)API 模块/命名空间。 因此,API::Amazon 在那之后不可用,但是 rerequireing lib/api/amazon.rb 没有帮助,因为它已经被需要,因此没有再次加载。 我将控制器更改为如下所示:

# app/controllers/api/v1/accounts_controller.rb
module API
  class V1::AccountsController < APIController
    ...
  end
end

现在它似乎工作正常。

【讨论】:

这似乎是/只是开发中的一个问题,在生产中从未发生过错误。【参考方案2】:

我写了一些代码来获得与你相同的结果,也许它可以提供一些线索。

trytemp.rb:

module API
  class Amazon
    def hello
      puts "API::Amazon initially works well"
      $stdout.flush
    end
  end
end

s = API::Amazon.new
s.hello

p API.constants
API = Module.new
p API.constants # Here you can see constant Amazon disappers from module API
s = API::Amazon.new
s.hello

它最初运行良好,然后得到相同的错误,“未初始化常量 API::Amazon (NameError)”:

$ ruby trytemp.rb
API::Amazon initially works well
[:Amazon]
trytemp.rb:15: warning: already initialized constant API
[]
trytemp.rb:19:in `<main>': uninitialized constant API::Amazon (NameError)

【讨论】:

你的代码有错误(如果我错了,请纠正我)。只有类不能初始化模块(Module.new)。 @maro30。你真的错了。您对 Module 和 Module 的实例感到困惑。例如,API 是 Module 的一个实例。也就是说,Module 是一个类,API 是一个模块。 ok 大写为MModule 来自哪里?如果API 是它的一个实例,那么Module 应该是一个类。只是想了解您的代码... 感谢您的建议,@uncutstone!由于您正在重新定义API (API = Module.new),因此您的代码出现错误是有道理的,因此之后API::Amazon 不再存在。我查看了我的项目,我能看到的唯一相关的事情是我的控制器有一个 api 命名空间,如下所示:class API::V1::AccountsController &lt; APIController。我会尝试将其更改为 module API; class V1::AccountsController &lt; APIController;... 以查看是否会改变任何内容... @Manuel Meurer。你解决问题了吗?您可以在代码中添加调试语句“p API.contants”,以查看常量 Amazon 何时从模块 API 中消失。我在上面的代码中添加了这样的调试语句。

以上是关于类是必需的,但无法访问的主要内容,如果未能解决你的问题,请参考以下文章

如何从对象获取值,但其类型无法访问

虚拟机上的Tomcat无法访问

家里WIFI显示已连接,但无法访问互联网是怎么回事?

win10无法访问局域网电脑,网络中可以搜索到其他计算机,但无法连接

电脑可以上网,其他都正常,但无法使用百度搜索,显示无法访问此网站

未找到源,但无法搜索部分或全部事件日志。无法访问的日志:安全 [重复]