Rails 6+默认的自动加载器是zeitwerk,这似乎比以前的方法有了很大的改进。
然而,zeetwork遵循Rails项目的惯例,即app/*
中的任何内容都是自动加载的,不需要使用名称空间。
这对app/models/user.rb
非常有效,因为您不必使用Models::User
,只需引用User
即可。
但是,我添加了自己的app/services
目录,并将服务对象命名为Services::Users::Create
,它将映射到app/services/users/create.rb
。
Zeetwork正在抛出我的类常量不存在的错误,因为它需要Users::Create
(没有Services::
前缀(。
在这些实例中,是否需要将zeetwork配置为需要Services::
命名空间?在我看来,将代码读取为Services::Users::Create
并知道您正在查找app/services/users/create.rb
文件会更干净。
如果您只有Users::Create
,一般Rails开发人员可能会查找app/models/users/create.rb
文件。
我不喜欢把它命名为Users::CreateService
的方法,它对我来说似乎很不雅
我不可能是唯一一个使用这种约定的人;有其他人想出解决方案吗?我仍在浏览所有的时代周刊文档,寻找解决方案,但还没有找到。
https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#having-自动加载路径中的应用程序
有些项目想要像app/api/base.rb这样的东西来定义api::base,并将应用程序添加到自动加载路径中,以在经典模式下实现这一点。由于Rails会自动将应用程序的所有子目录添加到自动加载路径中,因此我们遇到了另一种情况,即存在嵌套的根目录,因此安装程序不再有效。类似的原则,我们在上面解释了关切。
如果你想保持这种结构,你需要从初始化器中的自动加载路径中删除子目录:
ActiveSupport::Dependencies.autoload_paths.delete("#{Rails.root}/app/api")
我需要类似的东西,但对于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
来这里聚会有点晚,但情况非常相似!甚至将文件夹命名为"相同的东西";"服务";
这似乎有助于将其添加到application.rb文件中的自动加载路径:
config.autoload_paths += %W(#{config.root}/app/services/)
然后在子目录中,模块和类的定义如下:
#services/sub_folder/base.rb
module Services
class SubFolder::Base
end
end
我有一个类似的答案,这里有更多的细节。
然后在这里更新更多通用的Zeitwerk资源和提示。