Rails 5: cargar archivos lib en producción

128

He actualizado una de mis aplicaciones de Rails 4.2.6 a Rails 5.0.0. La Guía de actualización dice que la función de carga automática ahora está desactivada en producción de forma predeterminada.

Ahora siempre recibo un error en mi servidor de producción ya que cargo todos los archivos lib con carga automática en el application.rbarchivo.

module MyApp
    class Application < Rails::Application
        config.autoload_paths += %W( lib/ )
    end
end

Por ahora, me he fijado la config.enable_dependency_loadingque truepero me pregunto si hay una mejor solución a esto. Debe haber una razón por la que la carga automática está desactivada en la producción de forma predeterminada.

Tobias
fuente
locura, y los documentos todavía te dicen que hagas auto_load. Estaba muy confundido sobre lo que está mal en la producción de una nueva aplicación. Y desde que comencé a aprender con Rails 5 no leí la guía de migración. Archivé un problema de documentación para poder resolverlo: github.com/rails/rails/issues/27268
akostadinov
1
Sorprendentemente, tengo dos archivos en libdir, un archivo está fácilmente disponible en tiempo de ejecución, pero otro tiene que ser requerido manualmente: D
ilusionista
@Tobias ¿Con qué solución terminaste?
geoboy
@geoboy Agrupo el código (como Validators) en carpetas directamente en la aplicación / directorio ya que el código allí se carga automáticamente.
Tobias
se trata de la ruta del archivo adecuado y definición de la clase aquí es lo que el trabajo para mí en Rails 5.2: Ruta del archivo: app/services/paylinx/paylinx_service.rbDefinición de clase: module Paylinx class PaylinxService end end. Probé estas autoload_pathscosas. no funciona para mi
NamNamNam

Respuestas:

161

Mi lista de cambios después de pasar a Rails 5:

  1. Coloque libdir en appporque todo el código dentro de la aplicación se carga automáticamente en el desarrollador y se carga con entusiasmo en la producción y, lo más importante, se carga automáticamente en el desarrollo para que no tenga que reiniciar el servidor cada vez que realice cambios.
  2. Elimine todas las requiredeclaraciones que apunten a sus propias clases en el interior libporque todas se cargan automáticamente de todos modos si su nombre de archivo / directorio es correcto, y si deja requiredeclaraciones, puede interrumpir la recarga automática. Más información aquí.
  3. Establecer config.eager_load = trueen todos los entornos para ver los problemas de carga de código con entusiasmo en el desarrollador.
  4. Use Rails.application.eager_load!antes de jugar con hilos para evitar errores de "dependencia circular".
  5. Si tiene extensiones de ruby ​​/ rails, deje ese código dentro del libdirectorio anterior y cárguelos manualmente desde el inicializador. Esto asegurará que las extensiones se carguen antes de su lógica adicional que puede depender de ello:

    # config/initializers/extensions.rb
    Dir["#{Rails.root}/lib/ruby_ext/*.rb"].each { |file| require file }
    Dir["#{Rails.root}/lib/rails_ext/*.rb"].each { |file| require file }
Lev Lukomsky
fuente
8
Entonces, ¿cómo se usa la libcarpeta ahora? Quiero decir, mover el libdirectorio al appdirectorio parece una solución alternativa.
Martin Svoboda
3
/app/lib/coloca un archivo / clase y NO se carga automáticamente. probado en rails 5.1, nuevo proyecto
Tim Kretschmer
29
Vale la pena señalar que debes detener la primavera. Moví todo a app / lib / y luego perdí un poco de tiempo preguntándome por qué todavía no podía usar mis clases desde la consola. spring stop ftw :)
jacklin
1
¿Dónde iría la siguiente líneaRails.application.eager_load!
Steven Aguilar
1
Esto puede funcionar, pero no es la mejor solución. La estructura de carpetas también es semántica. Las cosas en libtienen una cercanía percibida diferente al proyecto que las cosas en el appdirectorio. Varias de las otras respuestas son mejores que esta.
CWitty
84

Acabo de usar en config.eager_load_pathslugar de config.autoload_pathsmencionar akostadinov en el comentario de github: https://github.com/rails/rails/issues/13142#issuecomment-275492070

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

Funciona en entornos de desarrollo y producción.

Gracias Johan para la sugerencia de reemplazar #{Rails.root}/libcon Rails.root.join('lib')!

Michał Zalewski
fuente
3
Funciona de maravilla. No me gustaba la sintaxis, así que la cambié a config.eager_load_paths << Rails.root.join('lib').
3limin4t0r
2
Para mí esa fue la mejor respuesta. Mi proyecto comenzó en Rails 5.2 desde cero y la carpeta / lib todavía se creó fuera de la carpeta / app. No vi una buena razón para moverlo.
Samir Haddad
1
Sí, esto funciona! Parece que los desarrolladores de Rails realmente disfrutan causando problemas de carga de lib: D hasta la próxima.
Damien Roche
To Rails 5.2 utiliza en su config.eager_load_paths += [Rails.root.join('lib')]lugar porque config.eager_load_pathses una matriz congelada
William Wong Garay
@WilliamWongGaray config.eager_load_paths es de solo lectura cuando intenta modificarlo en el inicializador. Cuando agregue rutas application.rb, funcionará utilizando ambos métodos.
Michał Zalewski
31

La carga automática está desactivada en el entorno de producción debido a la seguridad del hilo. Gracias a @ Зелёный por el enlace.

Resolví este problema almacenando los archivos lib en una libcarpeta en mi appdirectorio como se recomienda en Github . appRails carga automáticamente cada carpeta de la carpeta.

Tobias
fuente
66
Si no desea profundizar en el largo hilo de discusión en Github, puede encontrar una explicación destilada aquí: collectiveidea.com/blog/archives/2016/07/22/…
Ernest
77
Solía config.eager_load_paths << "#{Rails.root}/lib", eso es mejor IMO para seguir la estructura recomendada de la aplicación rails.
akostadinov
2
Los app/libmiembros de rails recomiendan poner lib en github.com/rails/rails/issues/13142#issuecomment-275549669
eXa
44
Esto arruina completamente cuál es el propósito de lib. Esperaría a que entrara tiernamente o DHH. Mientras tanto, (personalmente) recomendaría seguir con la respuesta de @Lev Lukomsky.
Josh Brody
@JoshBrody Mi opinión ahora es que no debería necesitar el /libdirectorio en absoluto. La mayoría de las veces, las bibliotecas de terceros son gemas y, si no, debería crearse una gema. Para otros archivos, creo carpetas específicas en el /appdirectorio. Por ejemplo validators.
Tobias
22

Debe haber una razón por la que la carga automática está desactivada en la producción de forma predeterminada.

Aquí hay una larga discusión sobre este tema. https://github.com/rails/rails/issues/13142

Зелёный
fuente
1
Esta discusión es la mejor, aunque una lectura larga, fuente de información sobre el tema que he encontrado.
Jason
12

Esto permite tener una carga automática de lib, y también funciona en un entorno de producción.

PD: He cambiado mi respuesta, ahora se agrega a las dos rutas de carga automática y ansiosa, independientemente del entorno, para permitir trabajar también en entornos personalizados (como la etapa)

# config/initializers/load_lib.rb
...
config.eager_load_paths << Rails.root.join('lib')
config.autoload_paths << Rails.root.join('lib')
...
srghma
fuente
2
¿Podría explicar por qué esto soluciona el problema?
Stuart.Sklinar
@ Stuart.Sklinar esto permite tener una recarga automática de lib, y también funciona en un entorno de producción. PD: He cambiado mi respuesta, ahora se suma a las dos rutas de carga automática e impaciente, independientemente del entorno, para permitir trabajar también en entornos personalizados (como la etapa)
srghma
1
¿Podría ampliar (en su respuesta)? Las respuestas de solo código no ayudan realmente a nadie a entender por qué se debe hacer "de esa manera". Debo agregar que no soy un desarrollador de Ruby, solo estoy ayudando a aclarar SO. Agregar algún comentario a una "respuesta de solo código" le daría un contexto real.
Stuart.Sklinar
1
@ Stuart.Sklinar seguro
srghma
6

Simplemente cambie config.autoload_paths a config.eager_load_paths en el archivo config / application.rb. Porque en rails 5 la carga automática está desactivada para el entorno de producción de forma predeterminada. Para más detalles por favor siga el enlace .

 #config.autoload_paths << "#{Rails.root}/lib"
  config.eager_load_paths << Rails.root.join('lib')

Funciona tanto para el desarrollo del medio ambiente como para la producción.

Jitendra Rathor
fuente
4

En cierto sentido, aquí hay un enfoque unificado en Rails 5 para centralizar la configuración ansiosa y de carga automática, al mismo tiempo que agrega la ruta de carga automática requerida cada vez que se configura la carga ansiosa; de lo contrario, no podrá funcionar correctamente:

# config/application.rb
...
config.paths.add Rails.root.join('lib').to_s, eager_load: true

# as an example of autoload only config
config.paths.add Rails.root.join('domainpack').to_s, autoload: true
...
pocheptsov
fuente
0

Mover la carpeta lib a la aplicación ayudó a resolver un problema, mi API de Twitter no se ejecutaba en producción. Tenía "TwitterApi constante sin inicializar" y mi API de Twitter estaba en mi carpeta lib. Tenía config.autoload_paths += Dir["#{Rails.root}/app/lib"]en mi application.rb pero no funcionó antes de mover la carpeta.

Esto hizo el truco

Laurie
fuente
-6

para resumir la respuesta de Lev: mv lib appfue suficiente para libcargar y cargar automáticamente todo mi código.

(Rails 6.0.0beta3 pero también debería funcionar bien en rails 5.x)

localhostdotdev
fuente