如何解决Rails`NameError:uninitialized constant`仅在生产环境中非控制台-类在/ app子文件夹中-需要添加双冒号`::`
在Rails 5.2应用程序中,我有一个Foos::SomethingSerializer
类,存储在app/serializers/foos/something_serializer.rb
中。
在开发中,此控制器代码可以正常工作:
# api/v1/foos_controller.rb
render json: Foos::SomethingSerializer.new(foo).as_json
仅在生产中,此代码引发异常NameError: uninitialized constant Api::V1::Foos::SomethingSerializer
我以前有过这个,所以我刚在它前面添加了::
,例如:
# api/v1/foos_controller.rb
render json: ::Foos::SomethingSerializer.new(foo).as_json
我可以称之为一天,但我真的会想了解这一点,因为这些只在生产中受到影响的错误是最糟糕的。
此外,控制台中的Rails.configuration.eager_load_paths显示/app/serializers
处于应有的自动加载路径上,因为它是app/
的子文件夹。
此外,在生产环境控制台中,我可以毫无例外地键入Foos::SomethingSerializer.new
(这样它将找到常量)。
那么为什么(1)在开发中起作用并且(2)在生产中会抛出异常,试图在控制器内部找到该命名空间常量,而在上层Foos
命名空间上找不到它?
解决方法
Ruby具有相对恒定的查找。
module A
class B
def self.c
C # note that it's not A::C
end
end
end
module A
class C
end
end
class C
end
C # C < Object
A::B.c # A::C < Object
如果它可以找到一个相对于您所处位置的常数,则它将返回该常数。如果它无法在当前上下文中找到该常量,它将升至一个级别并在那里寻找它,直到达到根级别为止。如果在根级别上找不到该常量,则会引发错误。
在::
之前加上常数,指示ruby从根目录开始查找。
在代码中,您同时定义了::Foos
和Api::V1::Foos
。从Foos::SomethingSerializer
内部调用Api::V1
时,ruby会找到Api::V1::Foos
而不是::Foos
,但是那里没有SomethingSerializer
,因此它将失败。我知道这很不方便,我个人也不喜欢它,但是事实就是这样。如果您知道要从根目录查找某些内容,则始终将::
添加为 是安全的。
开发并没有失败,因为您已经自动加载了。当您调用Foos::SomethingSerializer
时,尚未加载Api::V1::Foos
,并且由于已经加载了::Foos
,因此Rails找到了它,并且没有尝试自动加载Api::V1::Foos
。
我建议您使用eager_load = true
运行规范以尝试捕获此类错误,并在根上下文和嵌套上下文中具有相同名称的常量时使用根级查找(::
)。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。