У меня есть этот код /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. Но я думаю, что это не правильное решение.
Есть идеи по этому поводу?





Да, вы правы, но вместо использования относительного пути используйте свой код, как это было раньше, с указанным файлом, если вы хотите загрузить только один файл.
В своем version.rb используйте приведенный ниже код.
lib/my_app/version.rb
module MyApp
VERSION = '3.0.7'.freeze
end
Здесь .freeze определяет константу в вашем файле, и она загрузится Zeitwerk(Autoloader of your app).
Это решит вашу проблему.
Можете ли вы просто поделиться более подробной информацией о вашей ошибке? @Кайл
Это все то же самое, uninitialized constant MyApp::VERSION (NameError) И если я добавлю config.eager_load_paths << Rails.root.join("lib"), он не сможет запуститься и выдаст ошибку, как я объяснил в вопросе.
@Кайл, добавив config.eager_load_paths << Rails.root.join("lib") к своему application.rb, ты перезапускаешь приложение. Верно?
Да, конечно @Акшай
Вы изменили конфигурацию Zeitwork? @Кайл. в противном случае он должен работать правильно с вашим путем к папке lib.
@Кайл, используйте это в своем приложении config.autoload_paths += Dir[Rails.root.join('lib', '**/')].
Это просто плохой ответ. Вам не нужен отдельный файл для простых констант. Это не класс или модуль.
Здесь может быть несколько вещей.
Во-первых, если lib нет в путях автозагрузки, Zeitwerk не управляет файлом. Вам придется загрузить его вручную, и это совершенно нормально.
Затем, если lib находится в путях автозагрузки, вам нужно сообщить инфлектору автозагрузчика, что my_app/version.rb следует камелизировать как VERSION, а не Version. Пожалуйста, ознакомьтесь с руководством по автозагрузке.
Наконец, в этом случае вы не сможете ссылаться на константу во время загрузки приложения, поскольку во время загрузки перезагружаемые константы недоступны. Пожалуйста, дайте мне знать, если вам это нужно, и я свяжусь с вами.
Я действительно не думаю, что вам следует настраивать перегиб, поскольку эта константа вообще не должна автоматически загружаться. Нет веских причин для возможной поломки, если ваше приложение когда-нибудь захочет использовать Version в качестве названия модели в будущем.
Как я уже сказал, перегиб необходим ПРИ ПРЕДПОЛАГАНИИ, что вы хотите, чтобы файл загружался автоматически. В противном случае применяется второй абзац ответа. Во-вторых, с помощью Zeitwerk вы можете настраивать изменения вплоть до отдельного файла, они не обязательно должны быть глобальными.
Если вы хотите просто создать версию своего приложения 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 устанавливает инфлектор драгоценных камней, который автоматически создает для вас специальный регистр файла версии).
@XavierNoria что-то вроде. Обычные константы нарушают схему перегиба, поскольку по соглашению они пишутся заглавными буквами, и довольно редко у вас есть константа, которая действительно требует нахождения в отдельном файле, а не в модуле или константе. Версия драгоценного камня является своего рода исключением, которое подтверждает правило, поскольку в настройке загрузчика драгоценного камня она рассматривается как особый случай.
Нет, нет, я не согласен. Пользователи могут размещать константы где угодно, если они следуют соглашениям. Это поддерживается и является общепринятой практикой на усмотрение пользователя. Zeitwerk обеспечивает автозагрузку произвольных констант, а не автозагрузку классов/модулей. Если вы хотите поместить целое число в один файл, вы можете это сделать, это поддерживается, а конструкция инфлекторов такова, что вы можете, если хотите, преобразовать его по отдельному файлу. (Отказ от ответственности: я являюсь автором Zeitwerk.)
Да, но действительно ли это дает что-то положительное для качества кода? Это моя точка зрения.
Наличие файла версии с константой, в которой хранится строка, не только очень распространено в Ruby, но и определенно не противоречит моему представлению о качестве кода. Хотя я понимаю вашу точку зрения, для вас это важно.
Спасибо, но я попробовал ваше решение, и результат все тот же.