NameError: uninitialized constant #<Class:0x00007fadd32ea580>::Searchable

NameError: uninitialized constant #<Class:0x00007fadd32ea580>::Searchable

在 rspec 中调试一个不相关的问题时,我遇到了持续加载的问题。 设置如下:

# app/models/foo.rb

class Foo << ApplicationRecord
  include Foo::Searchable
end
# app/models/foo/searchable.rb

module Foo::Searchable
  extend ActiveSupport::Concern

  included do
    #yada yada
  end
end

我在调试时收到以下错误。 NameError: uninitialized constant #<Class:0x00007fadd32ea580>::Searchable 通过相应的文件夹移动将命名更改为 Foos::Searchable 确实可以解决问题,但我想了解实际发生的情况。

Rails 6.0.3.1 Ruby 2.6.6

也许您应该将 << 替换为 <。您继承,而不是重定向

class Foo < ApplicationRecord
  include Foo::Searchable
end

除了使用 << 而不是 < 之外,您还因为误用范围解析运算符 :: 而成为真正常见问题的受害者。在声明嵌套 类 或模块时不应使用它,因为它会导致错误的模块嵌套,并且会导致缺少常量错误,除非您嵌套的模块已经加载。

You should always explitly declare nested modules/classes:

class Foo < ApplicationRecord
  module Searchable
    extend ActiveSupport::Concern
    included do
      #yada yada
    end
  end
end

这个问题在过渡到 Rails 6 后随处可见的原因是旧的经典自动加载器过载 Module#const_missing 并掩盖了这些错误,因为它会自动加载 Foo。

Zeitwork 取代了经典的自动加载器,而是使用 Module#autoload,这是对 Ruby 的一个相对较新的补充,而且不那么骇人听闻。

原来是Byebug不兼容导致的。 Byebug 停止 Zeitwerk 用于在调试会话中自动加载的事件。问题描述为 here

<< 是一个拼写错误,不会导致该错误。