首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Zeitwerk::NameError由于rails 7中的模块名

Zeitwerk::NameError由于rails 7中的模块名
EN

Stack Overflow用户
提问于 2022-09-15 20:25:50
回答 2查看 168关注 0票数 1

最近,我将我的应用程序从rails 6升级到7,并且由于zeitwerk命名约定,我面临一个问题。我有一个下面的文件,我想自动下载:

代码语言:javascript
复制
app/models/dw/hospital.rb

module DW
  class Hospital < DataWarehouse
    def self.columns
      super.reject{|column| column.name == 'tableau_user' }
    end
  end
end

我尝试通过在我的application.rb文件中添加以下行来自动加载这个文件:

代码语言:javascript
复制
config.autoload_once_paths << 'app/models/dw'

但是,当我启动服务器时,我会得到以下错误:

代码语言:javascript
复制
expected file app/models/dw/hospital.rb to define constant Hospital, but didn't (Zeitwerk::NameError)

我不知道为什么会抛出这样的错误,因为常量已经定义好了。我怀疑这是因为我在类之前定义的模块。如果有人想解决这个问题,请告诉我。我被困在这里太久了。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-09-15 21:03:33

因为您已经将app/models/dw添加到自动路径中,所以必须定义Hospital,但是您的定义是名称空间的DW::Hospital。您不需要触摸自动配置,app/models已经在autoload_paths中了

代码语言:javascript
复制
>> ActiveSupport::Dependencies.autoload_paths
=> 
...
 "/home/alex/code/stackoverflow/app/jobs",
 "/home/alex/code/stackoverflow/app/mailers",
 "/home/alex/code/stackoverflow/app/models",   # <======
...

这就是所谓的https://github.com/fxn/zeitwerk#root-directories-and-root-namespaces。这意味着相对于app/models的文件结构必须对应于模块/类名。

因此,如果在任何根目录中都有dw/hospital.rb,那么就必须定义Dw::Hospital,这是您已经定义的。你也必须注意拐点,它应该是Dw,除非你有缩略词拐点规则或zeitwerk拐弯处:

代码语言:javascript
复制
>> "dw".camelize
=> "Dw"

ActiveSupport::Inflector.inflections(:en) do |inflect|
  inflect.acronym "DW" 
end  

>> "dw".camelize
=> "DW"

如果您必须使用嵌套根目录,那么您应该有一个很好的理由:

代码语言:javascript
复制
# if you want it to be reloadable,
# use `autoload_paths` instead of `autoload_once_paths`
config.autoload_paths << Rails.root.join("app/models/dw")

# app/models/dw/hospital.rb
class Hospital
end

但是正如泽维尔在评论中提到的那样,没有必要进行这种配置。使用默认配置,不要不必要地使设置复杂化。

票数 4
EN

Stack Overflow用户

发布于 2022-09-15 20:57:43

看起来大写的问题

通常,PascalCase (又名CamelCase)类名必须与snake_case文件名相对应。同样的规则也适用于命名空间和文件夹。

但是DWdw文件夹中(而不是Dw)

您可以创建如下的初始化程序

代码语言:javascript
复制
# config/initializers/zeitwerk.rb 

Rails.autoloaders.each do |autoloader|
  autoloader.inflector = Zeitwerk::Inflector.new
  autoloader.inflector.inflect(
    'dw' => 'DW',
    # other special cases
  )
end
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73737036

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档