You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将类移入嵌套/public目录后Zeitwerk常量缺失问题求助

问题描述

我正在使用packwerk将传统Rails应用重构为packages模块化结构:

  • 原目录结构:
- app
  - services
    - foo
  • 第一次重构后目录结构:
- packages
  - package_name
    - services
      - foo

此时在application.rb中添加了自动加载配置:

class Application < Rails::Application
  config.load_defaults 6.0

  # packwerk files
  config.paths.add 'packages', glob: '*/{*,*/concerns}', eager_load: true
end

Foo服务可通过Foo正常访问。但按照packwerk标准做法,创建public目录并将services移入其中后:

- packages
  - package_name
    - public
      - services
        - foo

调用Foo开始抛出uninitialized constant错误,尝试PackageName::Services::Foo、PackageName::Foo等路径也无效。

附上zeitwerk.rb初始化文件:

Rails.autoloaders.each do |autoloader|
  # See inflections.rb for inflector rules
  autoloader.inflector.inflect(
    "ai_wrapper" => "AIWrapper", # ActiveAdmin class
  )

  # ignore ActiveAdmin classes: without this line zeitwerk will match constants like Documents or DocumentFields
  # to /ops/admin classes instead of core/models directories
  autoloader.ignore(Rails.root.join('packages/ops/admin'))
end
解决方案

1. 调整自动加载路径配置

当前config.paths.add的glob规则未覆盖public目录下的内容,需要修改规则让Rails扫描到packages/*/public路径下的文件:

class Application < Rails::Application
  config.load_defaults 6.0

  # packwerk files:包含public目录下的文件
  config.paths.add 'packages', glob: '*/public/{*,*/concerns}', eager_load: true
end

如果需要同时兼容之前的非public结构和新的public结构,可将glob规则改为:

config.paths.add 'packages', glob: '*{,/public}/{*,*/concerns}', eager_load: true

2. 匹配常量命名与目录结构

按照Zeitwerk自动加载规则,packages/package_name/public/services/foo.rb对应的默认常量是Services::Foo(根命名空间下)。如果希望包内常量归属于PackageName命名空间,需在zeitwerk.rb中设置命名空间映射:

Rails.autoloaders.each do |autoloader|
  # 保留原有配置...

  # 为package_name包设置命名空间
  autoloader.push_dir(
    Rails.root.join('packages/package_name/public'),
    namespace: PackageName
  )
end

同时要确保foo.rb中的类定义与命名空间匹配:

module PackageName
  module Services
    class Foo
      # 类逻辑
    end
  end
end

此时即可通过PackageName::Services::Foo访问该类。

3. 清理缓存并重启服务器

修改自动加载配置后,需清理Rails缓存并重启服务器,确保配置生效:

rails tmp:clear
rails server

内容的提问来源于stack exchange,提问作者ntonnelier

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 16:45:44