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

时间:2019-11-21 18:52:53

标签: autoload ruby-on-rails-6 zeitwerk

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文档以寻找解决方案,但尚未找到解决方案。

2 个答案:

答案 0 :(得分:0)

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

一些项目想要app / api / base.rb之类的东西来定义API :: Base,然后将app添加到自动加载路径中以经典模式完成该任务。由于Rails会自动将应用程序的所有子目录添加到自动加载路径中,因此我们还有另一种情况,其中存在嵌套的根目录,因此设置不再起作用。我们在上文中曾解释过类似的原则,但很受关注。

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

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

答案 1 :(得分: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