Добавление lib в 'config.autoload_paths' в Rails 3 не выполняет автозагрузку моего модуля

Я помещаю имя файла g.rb в боковую папку Rails.root/lib Содержимое файла выглядит следующим образом:

module Google
end

Затем я добавляю

config.autoload_paths += %W(#{config.root}/lib #{Rails.root}/app/delayed_jobs)

на мой Rails.root/config/application.rb

Однако, когда я пытаюсь вызвать Google из rails console, генерируется исключение. Исключение уходит, только если я выполняю require 'google'. Зачем? Не должен ли мой файл загружаться автоматически и не должен ли я обращаться к модулю без каких-либо дополнительных инструкций require?

Ответ 1

Хм, я обнаружил интересную вещь. Чтобы Rails автоматически загружал мой класс, имя класса должно соответствовать имени файла и структуре папок. Например, если я хочу, чтобы модуль Google был автоматически загружен, я должен поместить его внутри google.rb, непосредственно под /lib (если я укажу autoload из /lib ). Если я хочу автонагрузку Google::Docs, то я либо помещаю ее внутри google.rb, либо google/docs.rb

Ответ 2

У меня была аналогичная проблема с тем, чтобы мой модуль работал на Heroku. В дополнение к соглашению об объявлении автозагрузки, указанному Stephen C, я обнаружил, что код модуля должен быть require 'd из-за допущения threadsafe, созданного производственной средой Rails на Heroku (хотя комментарий threadsafe был прокомментирован в моем конфигурационном файле production.rb.) Как только я require 'd файл модуля перед вызовом include в модуле, все приступило к работе.

require 'mymodule'
include Mymodule

Пожалуйста, взгляните на эту замечательную статью о том, как правильно загружать модули в Heroku (производство).

Ответ 3

Это потому, что точка автозагрузки не должна "требовать" все впереди (штраф за запуск). Занятия загружаются по мере необходимости. Для этого вам нужно каким-то образом узнать, где искать класс. В противном случае вам придется загружать каждый файл в каталог автозагрузки заранее, чтобы узнать, какие классы объявлены. Это компромисс, но требующий все заранее (как предполагает марбак) не является автозагрузкой. Вы можете использовать команду автозагрузку, как это предусмотрено Ruby, которая принимает два аргумента, модуль для загрузки (символизируется, то есть: Google в вашем случае), а второй аргумент это имя файла, который будет g.rb если Lib в вашей путь загрузки ($:). См. Документы Ruby для автозагрузки.

Ответ 5

Я столкнулся с той же проблемой только сейчас, и мое "решение" (или, скорее, обходное решение) состояло в том, чтобы вручную потребовать каждый необходимый файл из Rails.root/lib в моем приложении .rb.

require 'lib/message'
require 'lib/store'
require 'lib/vault/vault.rb'
require 'lib/custom_loggers'

module MyApplication
  class Application < Rails::Application

Следующим шагом будет категоризация файлов в папках модулей, как вы упомянули.

Ответ 6

Я недавно нашел это решение

конфигурации /application.rb

module AppName
  class Application < Rails::Application

    # Custom directories with classes and modules you want to be autoloadable.
    config.autoload_paths += Dir[Rails.root.join('app', 'models', '{**}')]
    config.autoload_paths += Dir[Rails.root.join('app', 'lib', 'extensions')] 

  end
end

первый вызов конфигурации вызывает рельсы для автоматической загрузки всех подкаталогов каталога app/models так что теперь я могу иметь /app/models/sub _directory/model.rb автозагрузку (удобно для организации приложения с большой базой кода)

второй вызов конфигурации вызывает рельсы для автозагрузки каталога lib/extensions

надеюсь, что это поможет

Примечание: я считаю, что это рельсы 3 конкретных