Carga automática de archivos lib en Rails 4


Uso la siguiente línea en un inicializador para cargar automáticamente el código en mi directorio /lib durante el desarrollo:

Config / inicializadores / personalizados.rb:

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

(desde Rails 3 Quicktip: Recarga automática de carpetas lib en modo desarrollo )

Funciona muy bien, pero es demasiado ineficiente para usarlo en producción: en lugar de cargar libs en cada solicitud, solo quiero cargarlas en el arranque. El mismo blog tiene otro artículo describiendo cómo hacer esto:

Configuración / aplicación.rb:

# 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/**/"]

Sin embargo, cuando cambio a eso, incluso en desarrollo, obtengo NoMethodErrors cuando intento usar las funciones lib.

Ejemplo de uno de mis archivos lib:

Lib / extensiones.rb:

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

Llamando Time.milli_stamp lanzará NoMethodError

Me doy cuenta de que otros han respondido preguntas similares sobre SO, pero todos parecen tratar con convenciones de nombres y otros problemas de los que no tenía que preocuparme antes - Mis clases lib ya funcionaban para la carga por solicitud, solo quiero cambiarla a por-inicio carga. ¿Cuál es la manera correcta de hacer esto?

Author: Yarin, 2013-09-30

4 answers

Creo que esto puede resolver su problema:

  1. En config/application.rb :

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

    Y mantenga la convención de nomenclatura correcta en lib.

    In lib/foo.rb :

    class Foo
    end
    

    In lib/foo/bar.rb :

    class Foo::Bar
    end
    
  2. Si realmente quieres hacer algunos parches de mono en el archivo como lib/extensions.rb , puede requerirlo manualmente:

    En config/inicializadores/require.rb :

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

P.d.

 532
Author: ifyouseewendy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-21 04:20:05

Aunque esto no responde directamente a la pregunta, pero creo que es una buena alternativa para evitar la pregunta por completo.

Para evitar todos los problemas autoload_paths o eager_load_paths, cree un directorio "lib" o un directorio "misc" en el directorio "app". Coloque los códigos como lo haría normalmente allí, y Rails cargará los archivos de la misma manera que cargará (y recargará) los archivos del modelo.

 32
Author: lulalala,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-21 03:59:39

Esto podría ayudar a alguien como yo que encuentre esta respuesta cuando busque soluciones a cómo maneja Rails la carga de clases ... Descubrí que tenía que definir un module cuyo nombre coincidiera con mi nombre de archivo apropiadamente, en lugar de simplemente definir una clase:

En el archivo lib/development_mail_interceptor.rb (Sí, estoy usando código de un Railscast :))

module DevelopmentMailInterceptor
  class DevelopmentMailInterceptor
    def self.delivering_email(message)
      message.subject = "intercepted for: #{message.to} #{message.subject}"
      message.to = "[email protected]"
    end
  end
end

Funciona, pero no se carga si no hubiera puesto la clase dentro de un módulo.

 6
Author: sameers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-25 17:01:26

Use config.to_prepare para cargar parches/extensiones de mono para cada solicitud en modo de desarrollo.

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"

Fin

 0
Author: Madx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-09 21:29:29