Лучший способ загрузить модуль / класс из папки 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);

12 ответов


с рельсов 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)

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

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

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


магия автозапуска

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

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

module Foo
  class Bar
  end
end

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


UPDATE: о типе магии..

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


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

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

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

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


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

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

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

в рамках приложения.рубидий...

require '/lib/this_file.rb' 

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

require './lib/this_file.rb' 

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

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


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

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

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

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

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

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

require 'mymodule'

в верхней части модели.файл rb.


есть несколько причин, по которым у вас могут возникнуть проблемы с загрузкой из lib-Подробнее см. здесь - http://www.williambharding.com/blog/technology/rails-3-autoload-modules-and-classes-in-production/

  • исправить путь автозагрузки
  • многопотоковое исполнение, связанных с
  • именования отношении
  • ...

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

пожалуйста, проверьте это Ссылка Для Обсуждения GitHub как хорошо.


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

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

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