5

Rails 6+ 默认的自动加载器是 zeitwerk,这似乎比以前的方法有了很大的改进。

但是,zeitwork 遵循 Rails 项目的约定,其中的任何内容app/*都是自动加载的,不需要命名空间。

这非常有用,app/models/user.rb因为您不必使用Models::User但可以参考User.

但是,我添加了自己的app/services目录并将我的服务对象命名为Services::Users::Create,这将映射到app/services/users/create.rb.

Zeitwork 抛出了我的类常量不存在的错误,因为它是预期Users::Create的(没有Services::前缀)。

无论如何配置 zeitwork 以Services::在这些实例中需要命名空间?Services::Users::Create在我看来,阅读代码并知道您正在查看app/services/users/create.rb文件会更干净。

如果您刚刚拥有Users::Create,一般的 Rails 开发人员可能会查找该app/models/users/create.rb文件。

我不喜欢命名它的方法Users::CreateService,这对我来说似乎很不雅。

我不能是唯一一个使用这样的约定的人;有没有其他人遇到过解决方案?我仍在浏览所有 zeitwerk 文档以寻找解决方案,但还没有找到解决方案。

4

3 回答 3

5

https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#have-app-in-the-autoload-paths

一些项目想要 app/api/base.rb 之类的东西来定义 API::Base,并将 app 添加到自动加载路径以在经典模式下完成此操作。由于 Rails 会自动将 app 的所有子目录添加到自动加载路径中,因此我们还有另一种情况,即存在嵌套的根目录,因此设置不再起作用。我们在上面解释的类似原理。

如果要保留该结构,则需要从初始化程序中的自动加载路径中删除子目录:

ActiveSupport::Dependencies.autoload_paths.delete("#{Rails.root}/app/api")
于 2019-12-20T09:24:27.093 回答
0

我需要类似的东西,但对于integrations. 我也不希望班级被调用Integrations::Base,而是Integration::Base

我创建了一个config/initializers/integrations.rb包含以下内容的文件:

ActiveSupport::Dependencies.autoload_paths.delete("#{Rails.root}/app/integrations")

autoloader = Rails.autoloaders.main
autoloader.push_dir(Rails.root.join("app"))
autoloader.inflector.inflect "integrations" => "Integration"

然后创建app/integrations/base.rb

module Integration
  class Base
  end
end
于 2020-11-06T08:56:14.970 回答
0

在这里聚会有点晚,但情况非常相似!甚至将文件夹命名为“服务”

这似乎有助于将其添加到 application.rb 文件中的自动加载路径:

config.autoload_paths += %W(#{config.root}/app/services/)

然后在子目录中,模块和类的定义如下:

#services/sub_folder/base.rb

module Services
  class SubFolder::Base
  end
end

我在这里有更详细的类似答案。

然后是更一般的Zeitwerk 资源和更新提示。

于 2021-09-15T04:46:47.817 回答