Константа модуля Rails не работала с Zeitwerk

У меня есть этот код /lib/my_app/version.rb

module MyApp
  VERSION = '3.0.7'
end

Когда я попробовал это MyApp::VERSION, я увидел эту ошибку: uninitialized constant MyApp::VERSION.

Затем я попытался добавить config.eager_load_paths << Rails.root.join("lib"), и произошла новая ошибка: expected file /Users/Documents/big_app/lib/my_app/version.rb to define constant MyApp::Version, but didn't (Zeitwerk::NameError)

Единственное решение, которое сработало для меня, — добавить require_relative '../lib/my_app/version' в файл конфигурации application.rb. Но я думаю, что это не правильное решение.

Есть идеи по этому поводу?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать 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
0
151
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Да, вы правы, но вместо использования относительного пути используйте свой код, как это было раньше, с указанным файлом, если вы хотите загрузить только один файл. В своем version.rb используйте приведенный ниже код.

lib/my_app/version.rb

module MyApp
  VERSION = '3.0.7'.freeze
end

Здесь .freeze определяет константу в вашем файле, и она загрузится Zeitwerk(Autoloader of your app).

Это решит вашу проблему.

Спасибо, но я попробовал ваше решение, и результат все тот же.

Kyle 08.05.2024 19:47

Можете ли вы просто поделиться более подробной информацией о вашей ошибке? @Кайл

Akshay Donga 08.05.2024 19:54

Это все то же самое, uninitialized constant MyApp::VERSION (NameError) И если я добавлю config.eager_load_paths << Rails.root.join("lib"), он не сможет запуститься и выдаст ошибку, как я объяснил в вопросе.

Kyle 08.05.2024 19:58

@Кайл, добавив config.eager_load_paths << Rails.root.join("lib") к своему application.rb, ты перезапускаешь приложение. Верно?

Akshay Donga 08.05.2024 20:00

Да, конечно @Акшай

Kyle 08.05.2024 20:02

Вы изменили конфигурацию Zeitwork? @Кайл. в противном случае он должен работать правильно с вашим путем к папке lib.

Akshay Donga 08.05.2024 20:11

@Кайл, используйте это в своем приложении config.autoload_paths += Dir[Rails.root.join('lib', '**/')].

Akshay Donga 09.05.2024 06:58

Это просто плохой ответ. Вам не нужен отдельный файл для простых констант. Это не класс или модуль.

max 09.05.2024 10:16

Здесь может быть несколько вещей.

Во-первых, если lib нет в путях автозагрузки, Zeitwerk не управляет файлом. Вам придется загрузить его вручную, и это совершенно нормально.

Затем, если lib находится в путях автозагрузки, вам нужно сообщить инфлектору автозагрузчика, что my_app/version.rb следует камелизировать как VERSION, а не Version. Пожалуйста, ознакомьтесь с руководством по автозагрузке.

Наконец, в этом случае вы не сможете ссылаться на константу во время загрузки приложения, поскольку во время загрузки перезагружаемые константы недоступны. Пожалуйста, дайте мне знать, если вам это нужно, и я свяжусь с вами.

Я действительно не думаю, что вам следует настраивать перегиб, поскольку эта константа вообще не должна автоматически загружаться. Нет веских причин для возможной поломки, если ваше приложение когда-нибудь захочет использовать Version в качестве названия модели в будущем.

max 09.05.2024 10:58

Как я уже сказал, перегиб необходим ПРИ ПРЕДПОЛАГАНИИ, что вы хотите, чтобы файл загружался автоматически. В противном случае применяется второй абзац ответа. Во-вторых, с помощью Zeitwerk вы можете настраивать изменения вплоть до отдельного файла, они не обязательно должны быть глобальными.

Xavier Noria 10.05.2024 02:14
Ответ принят как подходящий

Если вы хотите просто создать версию своего приложения Rails, вы можете просто сохранить его и поместить константу в config/application.rb, которая в любом случае требуется в процессе загрузки и включает модуль, инкапсулирующий ваше приложение.

# ...
module MyApp
  VERSION = '3.0.7'
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 7.0
  end
end

Единственное решение, которое сработало для меня, - это добавить require_relative '../lib/my_app/version' в файл конфигурации application.rb. Но я думаю, что это не правильное решение.

Это менее неправильно, чем ваша другая попытка.

Zeitwerk предназначен для загрузки классов и модулей в ваше приложение. Константы, представляющие собой простые скалярные значения, не требуют отдельного файла, а автозагружаемые константы недоступны во время загрузки.

В драгоценных камнях вы обычно включаете версию в файл lib/my_gem.rb, который в любом случае по большей части является шаблонным. Однако эмулировать это в приложении Rails не имеет особого смысла.

Если вам действительно нужен отдельный файл, который делается в некоторых драгоценных камнях просто для того, чтобы уменьшить количество изменений в истории версий файла gemspec, тогда вам просто нужно сделать это вручную.

require Rails.root.join('lib/my_app/version')

Однако опять же, имеет ли это какой-либо смысл в контексте приложения Rails?

lib в Rails обычно используется для кода, который не совсем вписывается в /app и не должен загружаться автоматически. Это чистилище, в котором живет код, пока его не извлекут в отдельный драгоценный камень. Это не совсем очевидное место для размещения чего-то простого конфигурации.

«На самом деле Zeitwerk предназначен для загрузки классов и модулей в ваше приложение». на самом деле это не так. Zeitwerk — это константы автозагрузки, их значения не имеют значения. Ваша рекомендация просто добавить это в config/application.rb хороша, и я поддерживаю ее, но наличие файла version.rb также является законным и очень идиоматическим в драгоценных камнях. Zeitwerk автоматически загружает файл version.rb в драгоценные камни (а for_gem устанавливает инфлектор драгоценных камней, который автоматически создает для вас специальный регистр файла версии).

Xavier Noria 10.05.2024 02:17

@XavierNoria что-то вроде. Обычные константы нарушают схему перегиба, поскольку по соглашению они пишутся заглавными буквами, и довольно редко у вас есть константа, которая действительно требует нахождения в отдельном файле, а не в модуле или константе. Версия драгоценного камня является своего рода исключением, которое подтверждает правило, поскольку в настройке загрузчика драгоценного камня она рассматривается как особый случай.

max 10.05.2024 08:40

Нет, нет, я не согласен. Пользователи могут размещать константы где угодно, если они следуют соглашениям. Это поддерживается и является общепринятой практикой на усмотрение пользователя. Zeitwerk обеспечивает автозагрузку произвольных констант, а не автозагрузку классов/модулей. Если вы хотите поместить целое число в один файл, вы можете это сделать, это поддерживается, а конструкция инфлекторов такова, что вы можете, если хотите, преобразовать его по отдельному файлу. (Отказ от ответственности: я являюсь автором Zeitwerk.)

Xavier Noria 10.05.2024 12:05

Да, но действительно ли это дает что-то положительное для качества кода? Это моя точка зрения.

max 10.05.2024 13:54

Наличие файла версии с константой, в которой хранится строка, не только очень распространено в Ruby, но и определенно не противоречит моему представлению о качестве кода. Хотя я понимаю вашу точку зрения, для вас это важно.

Xavier Noria 10.05.2024 20:41

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