Автоматическая загрузка lib файлов в Rails 4


я использую следующую строку в инициализаторе для автоматической загрузки кода в моем /lib каталог во время разработки:

config / инициализаторы / custom.РБ:

RELOAD_LIBS = Dir[Rails.root + 'lib/**/*.rb'] if Rails.env.development?

(от Rails 3 Quicktip: автоматическая перезагрузка папок lib в режиме разработки)

он отлично работает, но он слишком неэффективен для использования в производстве - вместо загрузки библиотек по каждому запросу я просто хочу загрузить их при запуске. Тот же блог другой статья описание того, как это сделать:

config / application.РБ:

# Custom directories with classes and modules you want to be autoloadable.
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]

однако, когда я переключаюсь на это, даже в разработке, я получаю NoMethodErrors при попытке использовать функции lib.

пример одного из моих lib-файлы:

lib / extensions.РБ:

Time.class_eval do
  def self.milli_stamp
    Time.now.strftime('%Y%m%d%H%M%S%L').to_i
  end
end

вызов Time.milli_stamp бросит NoMethodError

Я понимаю, что другие ответили на подобные вопросы, но они все кажется, я имею дело с соглашениями об именах и другими проблемами, о которых мне не нужно было беспокоиться раньше - мои классы lib уже работала для загрузки по запросу, я просто хочу изменить его на -startup загрузка. Как правильно это сделать?

4 217

4 ответа:

Я думаю, это может решить вашу проблему:

  1. на config / application.РБ:

    config.autoload_paths << Rails.root.join('lib')
    

    и сохранить правильное соглашение об именах в lib.

    на lib / foo.РБ:

    class Foo
    end
    

    на lib/foo / bar.РБ:

    class Foo::Bar
    end
    
  2. если вы действительно хотите сделать некоторые патчи в файл, как lib / extensions.РБ, вы можете вручную требуют это:

    на config / инициализаторы / require.РБ:

    require "#{Rails.root}/lib/extensions" 
    

П. С.

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

чтобы избежать всех autoload_paths или eager_load_paths проблемой, создать "либерал" или "смешанная" КАТАЛОГ "КАТАЛОГ приложения". Поместите коды, как вы обычно делаете там, и Rails будет загружать файлы так же, как он будет загружать (и перезагружать) файлы модели.

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

в файле lib / development_mail_interceptor.РБ (Да, я использую код из Railscast :))

module DevelopmentMailInterceptor
  class DevelopmentMailInterceptor
    def self.delivering_email(message)
      message.subject = "intercepted for: #{message.to} #{message.subject}"
      message.to = "myemail@mydomain.org"
    end
  end
end

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

используйте config.to_prepare для загрузки патчей/расширений monkey для каждого запроса в режиме разработки.

config.to_prepare do |action_dispatcher|
 # More importantly, will run upon every request in development, but only once (during boot-up) in production and test.
 Rails.logger.info "\n--- Loading extensions for #{self.class} "
 Dir.glob("#{Rails.root}/lib/extensions/**/*.rb").sort.each do |entry|
   Rails.logger.info "Loading extension(s): #{entry}"
   require_dependency "#{entry}"
 end
 Rails.logger.info "--- Loaded extensions for #{self.class}\n"

конец