Ошибка Rails 7 при запуске приложения - ошибки, связанные с Zeitwerk

Я обновляю свое приложение Rails с 6.1 до 7.0 и сталкиваюсь с этой ошибкой времени выполнения:

Я использую драгоценный камень Authlogic, но странно то, что у меня нет файла config/initializers для Authlogic, и я не могу найти ни одного экземпляра константы, с которой он не работает.

uninitialized constant Patches::AuthlogicPasswordPatch (NameError)
  /myapproot/shared/bundle/ruby/3.3.0/gems/zeitwerk-2.6.16/lib/zeitwerk/cref.rb:91:in `const_get'
  /myapproot/shared/bundle/ruby/3.3.0/gems/zeitwerk-2.6.16/lib/zeitwerk/cref.rb:91:in get

ОБНОВЛЕНИЕ: После решения вышеуказанной проблемы (решение см. в комментарии @alex ниже), следующая связанная проблема Zeitwerk:

Следующим препятствием является то, что Zeitwerk не имеет одинаковых имен классов, даже если они находятся в разных пространствах имен, что и вызывает эту ошибку:

Exception Zeitwerk::NameError in Rack application object 
(expected file app/services/data_tables/base.rb to define 
constant Base, but didn't)

когда я включил ведение журнала Zeitwerk и запустил приложение, я увидел это:

[email protected]: file app/services/deployment/models/base.rb is ignored because app/services/data_tables/base.rb has precedence

app/services/deployment/models/base.rb определяется как:

module Deployment
  module Models
    class Base < ActiveResource::Base
   ...

и app/services/data_tables/base.rb это:

module DataTables
  class Base
  ...

это то, что у меня есть в config/application.rb:

config.autoload_paths += Dir["#{config.root}/app/services/**/"]
config.eager_load_paths << "#{Rails.root}/lib"
config.eager_load_paths << "#{Rails.root}/app/services"

у вас есть файл patches/authlogic_password_patch.rb где-то в путях автозагрузки, который должен определять Patches::AuthlogicPasswordPatch

Alex 19.07.2024 19:14

Может быть, вы заходите сюда guides.rubyonrails.org/… ?

Xavier Noria 19.07.2024 22:57

@Алекс, ты был прав. мне пришлось исправить именно тот файл, у которого также было другое имя класса, а также добавить Module Patches вокруг класса, прежде чем эта ошибка была устранена. Есть больше ошибок, когда Zeitwerk не работает с дополнительными файлами классов. Могу ли я добавить сюда более подробную информацию или мне следует закрыть этот пост и создать новый? Не был уверен, каковы рекомендации SO для этого.

weetch 20.07.2024 01:11

Если проблема в содержимом файла, то странно, что в 6.1 это работало, а в 7.0 не работало. Также странно, что исключением является NameError, а не Zeitwerk::NameError, если это связано с автозагрузкой.

Xavier Noria 20.07.2024 07:57

спасибо, @Алекс. Я обновил вопрос, добавив дополнительную информацию.

weetch 20.07.2024 16:51

@XavierNoria, я добавил больше деталей к вопросу, а также пояснил, что ошибка действительно отображается как Zeitwerk::NameError. Я думаю, что Zeitwerk был необязательным в Rails 6.1, и, вероятно, поэтому этого не произошло, пока я не обновился до Rails 7.0.

weetch 20.07.2024 17:18

@weetch Я подозреваю, что ваше приложение может содержать подстановочные знаки в конфигурации autoload_paths. Пожалуйста, ознакомьтесь с этим разделом инструкции по миграции guides.rubyonrails.org/… . Если вы не читали это руководство, я бы порекомендовал его.

Xavier Noria 20.07.2024 21:04

@XavierNoria, вот что у меня есть в config/application.rb: config.autoload_paths += Dir["#{config.root}/app/services/**/"]&#10; config.eager_load_paths << "#{Rails.root}/lib"&#10; config.eager_load_paths << "#{Rails.root}/app/services"&#10; это не правильно?

weetch 20.07.2024 21:09

@weetch нет, это не так. Пожалуйста, прочтите этот раздел руководства.

Xavier Noria 20.07.2024 21:14

Я предлагаю вам удалить все autoload_paths и просто исправить структуру файлов. подкаталоги app уже настроены как пути автозагрузки. Я не удивлен, что из-за этого у тебя возникают все эти проблемы.

Alex 20.07.2024 21:22

спасибо, @XavierNoria. ты был прав. Это исправление решило все оставшиеся проблемы. Я опубликовал краткий обзор исправлений.

weetch 21.07.2024 00:52
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
11
92
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Добавление сводки исправлений, сделанных здесь, на случай, если это поможет другим. Спасибо @XavierNoria и @Alex за помощь.

Первоначальная причина заключалась в устаревшем файле исправления для Authlogic, названном так, как не понравилось Zeitwerk. В итоге я провел рефакторинг кода, чтобы полностью избавиться от файла, но если у вас есть файлы в lib/patches, вам нужно будет заключить код в пространство имен Module Patches.

Другая проблема заключалась в том, что в ряде классов Zeitwerk отказывался автоматически загружать классы с одинаковыми именами (хотя они явно находились внутри разных пространств имен/структур папок). Исправление заключалось в замене этой строки pre-rails-7.0 в config/application.rb:

config.autoload_paths += Dir["#{config.root}/app/services/**/"]

с:

config.autoload_paths += Dir["#{config.root}/app/services"]

Это решило все проблемы конфликта имен классов.

Патчи для драгоценных камней не должны быть автоматически загружаемыми/перезагружаемыми, поскольку изменения в этих файлах обычно не оказывают никакого влияния на драгоценный камень. Идиоматический способ настроить эту настройку — указать автозагрузчику игнорировать lib/patches (либо Rails.autoloaders.main.ignore("#{Rails.root}/lib/patches"), либо передать patches в список игнорирования config.autoload_lib, если он у вас есть). Затем при загрузке требуются файлы как обычно. Кроме того, поскольку эти файлы не будут управляться автозагрузчиками, для них не требуется никаких соглашений.

Xavier Noria 21.07.2024 09:09

Другие вопросы по теме