¿La mejor manera de cargar módulo / clase desde la carpeta lib en Rails 3?


Desde la última versión de Rails 3 ya no se cargan automáticamente módulos y clases de lib, ¿cuál sería la mejor manera de cargarlos?

De 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);
Author: Vincent, 2010-07-28

12 answers

A partir de Rails 2.3.9 , hay una configuración en config/application.rb en la que puede especificar los directorios que contienen los archivos que desea cargar automáticamente.

De la solicitud.rb:

# Custom directories with classes and modules you want to be autoloadable.
# config.autoload_paths += %W(#{config.root}/extras)
 248
Author: Slobodan Kovacevic,
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
2012-06-18 21:53:21
# Autoload lib/ folder including all subdirectories
config.autoload_paths += Dir["#{config.root}/lib/**/"]

Source: Rails 3 Quicktip: Autoload lib directory including all subdirectories, avoid lazy loading

Tenga en cuenta que los archivos contenidos en la carpeta lib solo se cargan cuando se inicia el servidor. Si desea la comodidad de cargar automáticamente esos archivos, lea: Rails 3 Quicktip: Auto reload lib folders in development mode . Tenga en cuenta que esto no está destinado a un entorno de producción, ya que la recarga permanente ralentiza la máquina.

 195
Author: thankful,
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-07-03 05:49:44

La magia de la carga automática de cosas

Creo que la opción de controlar las carpetas desde las que se realiza la carga automática ha sido suficientemente cubierta en otras respuestas. Sin embargo, en caso de que alguien más esté teniendo problemas para cargar cosas aunque hayan modificado sus rutas de carga automática según sea necesario, esta respuesta intenta explicar cuál es la magia detrás de esta cosa de carga automática.

Así que cuando se trata de cargar cosas de subdirectorios hay un gotcha o una convención que debe ser consciente. A veces la magia de Ruby/Rails (esta vez mayormente Rails) puede hacer difícil entender por qué algo está sucediendo. Cualquier módulo declarado en las rutas de carga automática solo se cargará si el nombre del módulo corresponde al nombre del directorio padre. Así que en caso de que intente poner en lib/my_stuff/bar.rb algo como:

module Foo
  class Bar
  end
end

No se cargará automáticamente. Por otra parte, si cambia el nombre del directorio padre a foo alojando así su módulo en path: lib/foo/bar.rb. Estará ahí para ti. Otra opción es nombre el archivo que desea cargar automáticamente por el nombre del módulo. Obviamente solo puede haber un archivo con ese nombre entonces. En caso de que necesite dividir sus cosas en muchos archivos, por supuesto, podría usar ese archivo para requerir otros archivos, pero no lo recomiendo, porque entonces cuando está en modo de desarrollo y modifica esos otros archivos, Rails no puede recargarlos automáticamente por usted. Pero si realmente lo desea, podría tener un archivo por el nombre del módulo que luego especifica los archivos reales necesarios para usa el módulo. Así que podrías tener dos archivos: lib/my_stuff/bar.rb y lib/my_stuff/foo.rb y el primero siendo el mismo que el anterior y el segundo conteniendo una sola línea: require "bar" y eso funcionaría igual.

P.D. Me siento obligado a añadir una cosa más importante. A partir de últimamente, cada vez que quiero tener algo en el directorio lib que necesita ser cargado automáticamente, tiendo a empezar a pensar que si esto es algo que estoy desarrollando específicamente para este proyecto (que por lo general es, podría algún día convertirse en un fragmento" estático " de código utilizado en muchos proyectos o en un submódulo de git, etc.. en cuyo caso definitivamente debe estar en la carpeta lib) entonces tal vez su lugar no está en la carpeta lib en absoluto. Tal vez debería estar en una subcarpeta bajo la carpeta de la aplicación· Tengo la sensación de que esta es la nueva forma de hacer las cosas de rails. Obviamente, la misma magia está en funcionamiento en cualquier lugar en el que cargue automáticamente los caminos en los que ponga sus cosas, por lo que es bueno para estas cosas. De todos modos, esto es sólo lo que pienso sobre el tema. Tú eres libre para no estar de acuerdo. :)


ACTUALIZACIÓN: Sobre el tipo de magia..

Como severin señaló en su comentario, el núcleo "autoload a module mechanism" es parte de Ruby, pero las rutas de autoload no lo son. No necesitas Rails para hacer autoload :Foo, File.join(Rails.root, "lib", "my_stuff", "bar"). Y cuando intentara hacer referencia al módulo Foo por primera vez, entonces se cargaría para usted. Sin embargo, lo que Rails hace es que nos da una manera de intentar cargar cosas automáticamente desde carpetas registradas y esto ha sido implementado de tal manera que necesita asumir algo sobre las convenciones de nomenclatura. Si no se hubiera implementado así, entonces cada vez que haga referencia a algo que no está actualmente cargado tendría que ir a través de todos los archivos en todas las carpetas de carga automática y comprobar si alguno de ellos contiene lo que estaba tratando de referencia. Esto a su vez derrotaría la idea de la carga automática y la carga automática. Sin embargo, con estas convenciones en su lugar puede deducir del módulo/clase su tratando de cargar donde se podría definir y simplemente cargar eso.

 80
Author: Timo,
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
2016-04-05 15:10:03

Advertencia: si desea cargar el 'monkey patch' o 'open class' desde su carpeta 'lib', no utilice el enfoque 'autoload' !!!

  • "config.autoload_paths" approach: solo funciona si está cargando una clase que se define solo en un lugar. Si alguna clase ya ha sido definida en otro lugar, entonces no puede cargarla de nuevo con este enfoque.

  • "config / initializer / load_rb_file.rb" enfoque: siempre funciona! sea cual sea el objetivo la clase es una nueva clase o una "clase abierta" o "parche de mono" para la clase existente, ¡siempre funciona!

Para más detalles , ver: https://stackoverflow.com/a/6797707/445908

 40
Author: Siwei Shen申思维,
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-05-23 12:34:14

Muy similar, pero creo que esto es un poco más elegante:

config.autoload_paths += Dir["#{config.root}/lib", "#{config.root}/lib/**/"]
 26
Author: Brian Armstrong,
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
2011-10-02 07:46:29

En mi caso estaba intentando simplemente cargar un archivo directamente bajo el directorio lib.

Dentro de la aplicación.rb...

require '/lib/this_file.rb' 

No estaba funcionando, incluso en la consola y luego cuando intenté

require './lib/this_file.rb' 

Y rails carga el archivo perfectamente.

Todavía soy bastante novato y no estoy seguro de por qué funciona, pero funciona. Si alguien quisiera explicármelo, lo apreciaría :D Espero que esto ayude a alguien de cualquier manera.

 14
Author: Nick Res,
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
2013-10-15 01:44:20

Yo tenía el mismo problema. Así es como lo resolví. La solución carga el directorio lib y todos los subdirectorios (no solo el directo). Por supuesto, puede usar esto para todos los directorios.

# application.rb
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]
 7
Author: hjuskewycz,
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
2013-05-07 20:22:20

Config.autoload_paths no funciona para mí. Lo resuelvo de otra manera

Ruby on rails 3 no recarga automáticamente el código de la carpeta /lib. Lo resuelvo poniendo dentro ApplicationController

Dir["lib/**/*.rb"].each do |path|
  require_dependency path
end 
 5
Author: msa7,
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
2013-05-07 20:23:28

Si solo ciertos archivos necesitan acceso a los módulos en lib, simplemente agregue una instrucción require a los archivos que lo necesitan. Por ejemplo, si un modelo necesita acceder a un módulo, agregue:

require 'mymodule'

En la parte superior del modelo.archivo rb.

 4
Author: Mike Fischer,
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
2010-07-31 01:27:15

Hay varias razones por las que podría tener problemas para cargar desde lib-vea aquí para más detalles - http://www.williambharding.com/blog/technology/rails-3-autoload-modules-and-classes-in-production/

  • arreglar ruta de carga automática
  • threadsafe relacionados
  • naming relating
  • ...
 1
Author: Chris Kimpton,
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
2013-04-20 10:23:33

A partir de Rails 5, se recomienda poner la carpeta lib bajo app directory o en su lugar crear otros espacios de nombre significativos para la carpeta como services , presenters, features etc y ponerlo en el directorio de la aplicación para la carga automática por rails.

Por favor revisa este Enlace de Discusión de GitHub también.

 1
Author: Ashik Salman,
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
2018-03-02 11:25:20

Escribe el nombre del archivo correctamente.

En serio. Luché con una clase durante una hora porque la clase era Governance:: ArchitectureBoard y el archivo estaba en lib/governance/architecture_baord.rb (transpuestas O y A en "board")

Parece obvio en retrospectiva, pero fue el diablo rastreando eso. Si la clase no está definida en el archivo en el que Rails espera que esté basada en munging el nombre de la clase, simplemente no la va a encontrar.

 0
Author: David Hempy,
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-10-19 16:00:55