Rails 6+、zeitwerk自动加载器和命名空间常量



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资源和提示。

相关内容

  • 没有找到相关文章

最新更新