Лучший способ загрузить модуль/класс из папки lib в Rails 3?

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

Ответ 1

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

Из приложения .rb:

# Custom directories with classes and modules you want to be autoloadable.
# config.autoload_paths += %W(#{config.root}/extras)

Ответ 2

# Autoload lib/ folder including all subdirectories
config.autoload_paths += Dir["#{config.root}/lib/**/"]

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

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

Ответ 3

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

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

Итак, когда дело доходит до загрузки файлов из подкаталогов, вы получаете информацию или соглашение, о котором вы должны знать. Иногда магия 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, это дает нам возможность автоматически загружать материал из зарегистрированных папок, и это было реализовано таким образом, что ему нужно что-то принять в соглашениях об именах. Если бы это не было реализовано так, то каждый раз, когда вы ссылаетесь на то, что в настоящее время не загружено, ему придется проходить через все файлы во всех папках автозагрузки и проверять, содержит ли кто-нибудь из них то, что вы пытались ссылаться. Это, в свою очередь, победит идею автозагрузки и автозагрузки. Однако, используя эти соглашения, вы можете вычесть из модуля/класса вашу попытку загрузить, где это может быть определено, и просто загрузить это.

Ответ 4

Предупреждение: если вы хотите загрузить "патч обезьяны" или "открыть класс" из своей папки "lib", не используйте подход автозагрузка"!!!

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

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

Подробнее см. fooobar.com/questions/26149/...

Ответ 5

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

config.autoload_paths += Dir["#{config.root}/lib", "#{config.root}/lib/**/"]

Ответ 6

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

Внутри application.rb...

require '/lib/this_file.rb' 

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

require './lib/this_file.rb' 

и рельсы загружают файл отлично.

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

Ответ 7

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

# application.rb
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]

Ответ 8

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

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

Dir["lib/**/*.rb"].each do |path|
  require_dependency path
end 

Ответ 9

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

require 'mymodule'

в верхней части файла model.rb.

Ответ 11

Заполните имя файла правильно.

Серьезно. Я сражался с классом в течение часа, потому что класс был Governance:: ArchitectureBoard, и файл находился в lib/management/architecture_baord.rb(транспонированный O и A на "доске" )

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