Лучший способ загрузить модуль / класс из папки lib в Rails 3? - PullRequest
270 голосов
/ 28 июля 2010

Поскольку последняя версия 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);

Ответы [ 12 ]

248 голосов
/ 28 июля 2010

Начиная с Rails 2.3.9 , в config/application.rb есть настройка, в которой вы можете указать каталоги, содержащие файлы, которые вы хотите загрузить автоматически.

Из application.rb:

# Custom directories with classes and modules you want to be autoloadable.
# config.autoload_paths += %W(#{config.root}/extras)
196 голосов
/ 18 октября 2010
# Autoload lib/ folder including all subdirectories
config.autoload_paths += Dir["#{config.root}/lib/**/"]

Источник: Подсказка по Rails 3: каталог автозагрузки lib, включающий все подкаталоги, избегайте отложенной загрузки

Обратите внимание, что файлы, содержащиеся в папке lib, загружаются только при запуске сервера. Если вы хотите, чтобы эти файлы автоматически загружались, прочитайте: Rails 3: подсказка: автоматическая перезагрузка папок lib в режиме разработки . Имейте в виду, что это не предназначено для производственной среды, поскольку постоянная перезагрузка замедляет работу машины.

82 голосов
/ 22 марта 2012

магия автозагрузки

Я думаю, что опция, управляющая папками, из которых выполняется автозагрузка, достаточно освещена в других ответах. Однако, если у кого-то еще возникают проблемы с загрузкой, хотя пути автозагрузки были изменены по мере необходимости, тогда этот ответ пытается объяснить, в чем заключается магия этой вещи автозагрузки.

Так что, когда дело доходит до загрузки материала из подкаталогов, есть недочёт или соглашение, о котором вы должны знать. Иногда магия Ruby / Rails (на этот раз в основном Rails) может затруднить понимание, почему что-то происходит. Любой модуль, объявленный в путях автозагрузки, будет загружен только в том случае, если имя модуля соответствует имени родительского каталога. Так что, если вы попытаетесь вставить в lib/my_stuff/bar.rb что-то вроде:

module Foo
  class Bar
  end
end

Он не будет загружен автоматически. Опять же, если вы переименуете родительский каталог в foo, тем самым разместив свой модуль по пути: lib/foo/bar.rb. Это будет там для вас. Другой вариант - назвать файл, который вы хотите загрузить, по имени модуля. Очевидно, что тогда может быть только один файл с таким именем. В случае, если вам нужно разделить ваши вещи на множество файлов, вы, конечно, можете использовать этот файл, чтобы требовать другие файлы, но я не рекомендую этого, потому что тогда, когда вы находитесь в режиме разработки, и вы изменяете эти другие файлы, Rails не может автоматически перезагрузите их для вас. Но если вы действительно хотите, вы можете иметь один файл с именем модуля, который затем указывает фактические файлы, необходимые для использования модуля. Таким образом, у вас может быть два файла: lib/my_stuff/bar.rb и lib/my_stuff/foo.rb, причем первый будет таким же, как указано выше, а последний содержит одну строку: require "bar", и это будет работать точно так же.

P.S. Я чувствую себя обязанным добавить еще одну важную вещь. В последнее время, когда я хочу, чтобы в каталоге lib было что-то, что нужно было автоматически загрузить, я начинаю думать, что если это то, что я на самом деле разрабатываю специально для этого проекта (что обычно бывает, это может когда-нибудь случиться) превратиться в «статический» фрагмент кода, используемого во многих проектах или в подмодуле git и т. д., и в этом случае он обязательно должен быть в папке lib), тогда, возможно, его место вообще не будет в папке lib. Возможно, это должно быть в подпапке в папке приложения. У меня такое ощущение, что это новый способ работы. Очевидно, что та же самая магия работает в тех местах, где вы используете пути автозагрузки, в которые вы помещаете свои вещи, так что это хорошо для этих вещей. Во всяком случае, это только мои мысли на эту тему. Вы можете не согласиться. :)


ОБНОВЛЕНИЕ: О типе магии ..

Как отметил Северин в своем комментарии, ядро ​​«автозагрузка модуля» определенно является частью Ruby, но пути автозагрузки - нет. Вам не нужны Rails, чтобы делать autoload :Foo, File.join(Rails.root, "lib", "my_stuff", "bar"). И когда вы попытаетесь сослаться на модуль Foo в первый раз, он будет загружен для вас. Однако, что делает Rails, так это то, что он дает нам возможность автоматически пытаться загружать вещи из зарегистрированных папок, и это было реализовано таким образом, что нужно что-то предполагать в соглашениях об именах. Если бы это не было реализовано таким образом, то каждый раз, когда вы ссылаетесь на то, что в данный момент не загружено, ему нужно будет просмотреть все файлы во всех папках автозагрузки и проверить, содержит ли какой-либо из них то, на что вы пытались сослаться. Это в свою очередь победило бы идею автозагрузки и автозагрузки. Тем не менее, с этими соглашениями он может вычесть из модуля / класса ваши попытки загрузить, где это может быть определено, и просто загрузить это.

41 голосов
/ 08 января 2013

Предупреждение: если вы хотите загрузить 'monkey patch' или 'open class' из папки 'lib', не используйте подход 'autoload' !!!Подход

  • " config.autoload_paths ": работает только при загрузке класса, определенного только в ОДНОМ месте.Если какой-то класс уже был определен где-то еще, вы не сможете загрузить его снова этим подходом.

  • " config / initializer / load_rb_file.rb ": всегда работает!независимо от того, является ли целевой класс новым классом, «открытым классом» или «обезьяньим патчем» для существующего класса, он всегда работает!

Подробнее см .: https://stackoverflow.com/a/6797707/445908

28 голосов
/ 02 октября 2011

Очень похоже, но я думаю, что это немного более элегантно:

config.autoload_paths += Dir["#{config.root}/lib", "#{config.root}/lib/**/"]
15 голосов
/ 15 октября 2013

В моем случае я пытался просто загрузить файл прямо в директории lib.

в приложении. Rb ...

require '/lib/this_file.rb' 

не работал, даже в консоли, а затем, когда я пытался

require './lib/this_file.rb' 

и rails отлично загружают файл.

Я все еще довольно нуб, и я не уверен, почему это работает, но работает. Если кто-то хотел бы объяснить это мне, я был бы признателен: D Я надеюсь, что это поможет кому-то в любом случае.

7 голосов
/ 22 сентября 2010

У меня была такая же проблема. Вот как я это решил. Решение загружает каталог lib и все его подкаталоги (не только прямые). Конечно, вы можете использовать это для всех каталогов.

# application.rb
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]
5 голосов
/ 18 октября 2011

config.autoload_paths не работает для меня.Я решаю это другим способом

Ruby on rails 3 не выполняет автоматическую перезагрузку (автозагрузку) кода из папки / libЯ решаю это, положив внутрь ApplicationController

Dir["lib/**/*.rb"].each do |path|
  require_dependency path
end 
4 голосов
/ 31 июля 2010

Если только определенным файлам нужен доступ к модулям в lib, просто добавьте оператор require к файлам, которые в нем нуждаются. Например, если одной модели требуется доступ к одному модулю, добавьте:

require 'mymodule'

вверху файла model.rb.

2 голосов
/ 02 марта 2018

Начиная с Rails 5, рекомендуется поместить папку lib в каталог приложения или вместо этого создать другие значимые пространства имен для папки как services, presenters, features и т. Д. И поместить ее в каталог приложения дляавтоматическая загрузка по рельсам.

Пожалуйста, отметьте GitHub Discussion Link .

...