Поскольку последний релиз Rails 3 больше не является автозагрузкой модулей и классов из lib, каков будет лучший способ их загрузки?
Из GitHub:
A few changes were done in this commit: Do not autoload code in *lib* for applications (now you need to explicitly require them). This makes an application behave closer to an engine (code in lib is still autoloaded for plugins);
app/lib
.Источник: Rails 3 Quicktip: Автозагрузка каталога lib, включая все подкаталоги, избегайте отложенной загрузки
Обратите внимание, что файлы, содержащиеся в папке lib, загружаются только при запуске сервера. Если вы хотите, чтобы эти файлы автоматически загружались , прочтите: Rails 3 Quicktip: Автоматическая перезагрузка папок lib в режиме разработки . Помните, что это не относится к производственной среде, поскольку постоянная перезагрузка замедляет работу машины.
источник
Магия автозагрузки
Я думаю, что опция, управляющая папками, из которых выполняется автозагрузка, достаточно освещена в других ответах. Тем не менее, в случае, если у кого-то еще возникают проблемы с загруженным материалом, хотя пути автозагрузки были изменены по мере необходимости, этот ответ пытается объяснить, в чем заключается магия этой вещи автозагрузки.
Поэтому, когда дело доходит до загрузки материалов из подкаталогов, есть недочёт или соглашение, о котором вы должны знать. Иногда магия Ruby / Rails (на этот раз в основном Rails) может затруднить понимание, почему что-то происходит. Любой модуль, объявленный в путях автозагрузки, будет загружен, только если имя модуля соответствует имени родительского каталога. Так что, если вы попытаетесь вставить
lib/my_stuff/bar.rb
что-то вроде:Он не будет загружен автоматически. Потом еще раз , если вы переименовать родительские директории для
foo
таким образом , хостинга для вашего модуля в пути:lib/foo/bar.rb
. Это будет там для вас. Другой вариант - назвать файл, который вы хотите загрузить автоматически, по имени модуля. Очевидно, что тогда может быть только один файл с таким именем. В случае, если вам нужно разделить ваши вещи на множество файлов, вы, конечно, можете использовать этот файл, чтобы требовать другие файлы, но я не рекомендую этого, потому что тогда, когда вы находитесь в режиме разработки, и вы изменяете эти другие файлы, Rails не может автоматически перезагрузите их для вас. Но если вы действительно хотите, вы можете иметь один файл с именем модуля, который затем указывает фактические файлы, необходимые для использования модуля. Таким образом , вы можете иметь два файла:lib/my_stuff/bar.rb
иlib/my_stuff/foo.rb
первый из них будет таким же, как указано выше, а второй будет содержать одну строку:require "bar"
и это будет работать точно так же.PS Я чувствую себя обязанным добавить еще одну важную вещь. В последнее время, когда я хочу, чтобы в каталоге lib было что-то, что нужно было загрузить автоматически, я начинаю думать, что если это то, что я на самом деле разрабатываю специально для этого проекта (что обычно бывает, это может когда-нибудь случиться) превратиться в «статический» фрагмент кода, используемого во многих проектах или в подмодуле git и т. д., в этом случае он обязательно должен быть в папке lib), тогда, возможно, его место вообще не будет в папке lib. Возможно, это должно быть в подпапке в папке приложения. У меня такое ощущение, что это новый способ работы. Очевидно, одна и та же магия работает в тех местах, где вы кладете свои вещи на пути автозагрузки, так что это хорошо для этих вещей. Во всяком случае, это только мои мысли на эту тему. Вы можете не согласиться. :)
ОБНОВЛЕНИЕ: О типе магии ..
Как отметил Северин в своем комментарии, ядро «автозагрузки модульного механизма», безусловно, является частью Ruby, а пути автозагрузки - нет. Вам не нужны Rails, чтобы сделать
autoload :Foo, File.join(Rails.root, "lib", "my_stuff", "bar")
, И когда вы попытаетесь сослаться на модуль Foo в первый раз, он будет загружен для вас. Однако, что делает Rails, так это то, что он дает нам возможность автоматически пытаться загружать вещи из зарегистрированных папок, и это было реализовано таким образом, что нужно что-то предполагать в соглашениях об именах. Если бы он не был реализован подобным образом, то каждый раз, когда вы ссылаетесь на что-то, что в данный момент не загружено, ему придется просматривать все файлы во всех папках автозагрузки и проверять, содержит ли какой-либо из них то, на что вы пытались сослаться. Это в свою очередь победило бы идею автозагрузки и автозагрузки. Тем не менее, с этими соглашениями он может вычесть из модуля / класса ваши попытки загрузить, где это может быть определено, и просто загрузить это.источник
Предупреждение: если вы хотите загрузить 'monkey patch' или 'open class' из папки 'lib', не используйте подход 'автозагрузка' !!!
Подход " config.autoload_paths ": работает, только если вы загружаете класс, который определен только в ОДНОМ месте. Если какой-то класс уже был определен где-то еще, таким способом вы не сможете загрузить его снова.
Подход " config / initializer / load_rb_file.rb ": всегда работает! независимо от того, является ли целевой класс новым классом, «открытым классом» или «обезьяньим патчем» для существующего класса, он всегда работает!
Для получения дополнительной информации см .: https://stackoverflow.com/a/6797707/445908.
источник
Очень похоже, но я думаю, что это немного более элегантно:
источник
В моем случае я пытался просто загрузить файл прямо в директории lib.
Внутри application.rb ...
не работал, даже в консоли, а потом, когда я пытался
и рельсы загружает файл отлично.
Я все еще довольно нуб, и я не уверен, почему это работает, но это работает. Если кто-то хотел бы объяснить это мне, я был бы признателен: Я надеюсь, что это поможет кому-то в любом случае.
источник
У меня такая же проблема. Вот как я это решил. Решение загружает каталог lib и все его подкаталоги (не только прямые). Конечно, вы можете использовать это для всех каталогов.
источник
Expected lib/bar/foo.rb to define constant Foo
если попытаетесь загрузить lib / foo.rb, ссылаясь на Foo постоянная.config.autoload_paths не работает для меня. Я решаю это по-другому
источник
Если только определенные файлы нуждаются в доступе к модулям в lib, просто добавьте оператор require к файлам, которые в нем нуждаются. Например, если одной модели требуется доступ к одному модулю, добавьте:
в верхней части файла model.rb.
источник
require
в приложении rails, потому что оно препятствуетActiveSupport::Dependencies
загрузке этого кода должным образом. Вместо этого вы должны использоватьconfig.autoload_paths
как ответ выше, а затем включить / расширить, как требуется.require
откуда-нибудь в приложении Rails? В задании на грабли я в настоящее время -require
иinclude
- модуль, который живет вlib/
. Разве я не должен этим заниматься?require
вашегоlib/
кода (например, этот пост в блоге , этот SO-ответ ). Я все еще не уверен в этом. Можете ли вы дать больше доказательств в пользу отказа от использованияrequire
?Назовите имя файла правильно.
Шутки в сторону. Я боролся с классом в течение часа, потому что класс был Governance :: ArchitectureBoard, а файл находился в lib / management / Architecture_baord.rb (транспонировал O и A в "board")
Кажется очевидным в ретроспективе, но это был дьявол, выслеживающий это. Если класс не определен в файле, в котором Rails ожидает, что он будет основан на обработке имени класса, он просто не найдет его.
источник
Начиная с этого
Rails 5
, рекомендуется поместить папку lib в каталог приложения или вместо этого создать другие значимые пространства имен для папки asservices
,presenters
иfeatures
т. Д. И поместить ее в каталог приложения для автоматической загрузки с помощью rails.Пожалуйста, проверьте также эту ссылку для обсуждения на GitHub .
источник
Есть несколько причин, по которым у вас могут возникнуть проблемы с загрузкой из lib - подробности см. Здесь - http://www.williambharding.com/blog/technology/rails-3-autoload-modules-and-classes-in-production/
источник