Пространство имен сервисных объектов в Rails 6 с автозагрузчиком Zeitwerk - PullRequest
1 голос
/ 05 августа 2020

Rails 6 переключился на Zeitwerk в качестве автозагрузчика по умолчанию. Zeitwerk загрузит все файлы в папку / app, устраняя необходимость в использовании пространств имен. Это означает, что объект службы TestService в app / services / demo / test_service.rb теперь может быть вызван напрямую, например, TestService.new().call.

Однако пространство имен было полезно для организации объектов в более сложных приложениях rails, например API :: UsersController , или для сервисов мы используем Registration :: CreateAccount, Registration :: AddDemoData et c.

Одно решение , предложенное в руководстве , - это удалите путь из пути автозагрузчика в application.rb, например, config.autoload_paths -= Dir["#{config.root}/app/services/demo/"]. Тем не менее, это похоже на обезьяний патч для замены старого способа или организации объектов новым способом рельсов.

Каков правильный способ размещения объектов в пространстве имен или способ организации рельсов 6 без того, чтобы просто вставлять рельсы в рельсы? старый способ?

1 Ответ

1 голос
/ 05 августа 2020

Неверно сказать, что Zeitwerk устраняет «необходимость в пространстве имен». Zeitwerk действительно автоматически загружает все подкаталоги app (кроме assets, javascripts и views). Все каталоги под app загружаются в пространство имен 'root'. Но Zeitwerk также «автоматически оживляет» модули для любых каталогов, находящихся в этих корнях. Итак:

/models/foo.rb => Foo
/services/bar.rb => Bar
/services/registration/add_demo_data.rb => Registration::AddDemoData

Если вы уже привыкли загружать константы из «нестандартных» каталогов (путем добавления в config.autoload_paths), обычно не так много изменений. Тем не менее, есть несколько случаев, которые требуют небольшой настройки. Первый - это когда вы переносите проект, который просто добавляет app в путь автозагрузки. В classi c (до Rails 6) это позволяет вам использовать app/api/base.rb, чтобы содержать API::Base, тогда как в Zeitwerk ожидается, что он будет содержать только Base. Это тот случай, о котором вы упомянули выше, когда рекомендуется исключить этот каталог из пути автозагрузки. Другой альтернативой было бы просто добавить каталог-оболочку, например app/api/api/base.rb.

Вторая проблема, которую следует отметить, - это то, как Zeitwerk выводит константы из имен файлов. Из руководства по миграции Rails:

classic режим выводит имена файлов из отсутствующих имен констант (подчеркивание), тогда как режим zeitwerk выводит имена констант из имен файлов (camelize). Эти помощники не всегда противоположны друг другу, особенно если используются акронимы. Например, "FOO".underscore это "foo", но "foo".camelize это "Foo", а не "FOO".

Итак, /api/api/base.rb фактически соответствует Api::Base в Zeitwerk, а не API::Base.

Zeitwerk включает задачу rake для проверки автозагрузки в проекте:

% bin/rails Zeitwerk:check
Hold on, I am eager loading the application.
expected file app/api/base.rb to define constant Base
...