Есть ли программный способ обнаружить Zeitwerk::NameError при обновлении до Rails 6?
В настоящее время я переношу старое приложение Rails на Rails 6.
Похоже, что некоторые файлы в проекте не соответствуют определенным в нем классам. Я не вижу этой ошибки при запуске тестов приложения, но после развертывания я получаю такие ошибки, как:
Zeitwerk::NameError: expected file /app/my?_/app/lib/multi_io.rb to define constant MultiIo, but didn't
В предыдущих вопросах SO я мог найти предложения:
- Rails 6: Zeitwerk::NameError не загружает класс из набора
модулей
config.autoloader = :classic
- Как игнорировать папку в Zeitwerk для Rails 6? игнорировать данный путь
- Автозагрузка и режим Zeitwerk в Rails 6 Tweak
config.autoload_path
Я не ищу обходного пути, поэтому исправил файл, вызывающий исключение.
Я хотел бы найти программный способ обнаружения всех несовместимых имен путей / классов без запуска приложения в производственном режиме.
Пока мне в голову пришло три варианта:
- Задача rake для проверки автозагрузки (которая не предоставляется гемом). Он существует? Не могли бы вы вместо этого запускать фрагмент из консоли rails в среде разработки?
- Рубокоп или другой статический анализатор кода. Существует какой-либо?
- Заставить нетерпеливую нагрузку в тестовой среде
Что это за предлагаемый подход к проверке моего кода без необходимости нескольких итераций / развертываний?
заранее большое спасибо
2 ответа
Вы можете проверить совместимость автозагрузки проекта с помощью
zeitwerk::check
задача:
$ bin/rails zeitwerk:check
Hold on, I am eager loading the application.
All is good!
Он выполняет все пути автозагрузки и помечает проблемы, например, вызванные изменением вывода имени константы (например, с акронимами). Задача не широко рекламируется или не документируется, за исключением руководства по обновлению. Но на самом деле я иногда использую его, чтобы просто избавиться от постоянных проблем с именованием в проекте в целом (то есть, когда класс не соответствует файлу).
@rmlockerd описал один из лучших инструментов для этого в своем ответе здесь .
Другие статьи, которые я нашел информативными, были:
- Понимание Zeitwerk в Rails
- 9 советов и приемов, которые помогут вам включить автозагрузчик Zeitwerk в вашем приложении Rails
- Документ Rails по обновлению с Rails 5.2 до 6.0
Процесс, который я взял, состоял в том, чтобы запустить
bin/rails zeitwerk:check
исправь ошибку, запусти еще раз, пока не увидишь "Все хорошо". После этого проработали ошибки, о которых сообщают наши тесты спецификации.
Одна общая проблема, которую необходимо исправить, заключается в том, что если папка не находится в файловой структуре Rails по умолчанию, Zeitwerk не сможет найти ее при автозагрузке. У нас была папка с именем «services» (
app/services
), который необходимо добавить в путь автозагрузки в файле application.rb, например:
config.autoload_paths += %W(#{config.root}/app/services/)
Ошибка:
Ожидаемый файл
path/file_name.rb
определить константу FileName
Документ Rails по автозагрузкеИсправить: удалить любой
require
или же
require_relative
в других файлах, ссылающихся на определение класса (Zeitwerk в них не нуждается).
Ошибка (класс определен в модуле подкаталога):
NameError: неинициализированная константа SubFile::ClassName
Подробно в другом ответе S/O. Всякий раз, когда метод используется в подпапках, структурируйте вызов как
Folder::SubDirectory::Class.method_call
Удачи!