commands - Ruby on Rails 3-Recarga el directorio lib para cada solicitud
rails spring (11)
Además, asegúrese de comentar la siguiente línea en application.rb (además de la solución de @disod) y asegúrese de que el nombre de su módulo sea el mismo que el de su archivo (de lo contrario, los rieles no podrán encontrarlo). )
#Dir.glob("./lib/*.{rb}").each { |file| require file } # require each file from lib directory
Estoy creando un nuevo motor para una aplicación Rails 3. Como puede adivinar, este motor está en el directorio lib de mi aplicación.
Sin embargo, tengo algunos problemas para desarrollarlo. De hecho, necesito reiniciar mi servidor cada vez que cambio algo en el motor.
Hay alguna manera de evitar esto ?
¿Puedo forzar que los rieles recarguen por completo el directorio lib o un archivo específico y sus requisitos para cada solicitud?
Gracias por tu ayuda :)
Agregue a application_controller.rb
o su controlador base:
before_filter :dev_reload if Rails.env.eql? ''development''
def dev_reload
# add lib files here
["rest_client.rb"].each do |lib_file|
ActiveSupport::Dependencies.load_file lib_file
end
end
Trabajó para mi.
Aquí está mi versión inspirada en la respuesta de @pbhogan que vuelve a cargar todos los archivos ruby en el directorio rails / lib cuando se cambia alguno de esos archivos.
También silencia las advertencias para evitar mensajes con respecto a las constantes ya inicializadas.
Funciona a partir de Rails 3.2.8
if Rails.env.development?
lib_ruby_files = Dir.glob(File.join("lib/**", "*.rb"))
lib_reloader ||= ActiveSupport::FileUpdateChecker.new(lib_ruby_files) do
lib_ruby_files.each do |lib_file|
silence_warnings { require_dependency(lib_file) }
end
end
ActionDispatch::Callbacks.to_prepare do
lib_reloader.execute_if_updated
end
end
Como estamos hablando de Rails, la forma más fácil es ''exigir'' sus archivos lib / * .rb usando '' require_dependency ''. Siempre que el controlador / helper / etc (archivos .rb en la aplicación /) use require_dependency en lugar de solo requerir que se vuelva a cargar, sin la necesidad de hacer nada funky.
Antes de ir por esa pista, la única solución que funcionaba era la de hemju.com , pero realmente no quería tener que hackear ApplicationController para la velocidad de desarrollo.
En RAILS 3, aquí está la salsa secreta para volver a cargar automáticamente los archivos lib. El código siguiente es un poco exagerado, por ejemplo, pero es lo que hice para que funcione. Puede cambiar el mensaje en YoYo # gogo y verlo en la pantalla cada carga de página. Elimina el inicializador y permanece igual.
/config/initializers/lib_reload.rb (archivo nuevo)
ActiveSupport::Dependencies.explicitly_unloadable_constants << ''YoYo''
ActiveSupport::Dependencies.autoload_once_paths.delete(File.expand_path(File.dirname(__FILE__))+''/lib'')
/lib/yo_yo.rb
class YoYo
def gogo
"OH HAI THERE"
end
end
/ app / controllers / home_controller
require ''yo_yo''
class HomeController < ApplicationController
def index
@message = YoYo.new.gogo
end
end
Funcionó para Rails 3.2.13 para volver a cargar lib dentro de la joya de una aplicación:
require_dependency ''the_class''
Y
config.autoload_paths + =% W (# {config.root} /../ fantasy / lib)
No pude hacer nada de lo anterior para trabajar para mí, así que profundicé un poco en el código de Rails y se me ocurrió esto:
Nuevo archivo: config / initializers / reload_lib.rb
if Rails.env == "development"
lib_reloader = ActiveSupport::FileUpdateChecker.new(Dir["lib/**/*"]) do
Rails.application.reload_routes! # or do something better here
end
# For Rails 5.1+
ActiveSupport::Reloader.to_prepare do
lib_reloader.execute_if_updated
end
# For Rails pre-5.1
ActionDispatch::Callbacks.to_prepare do
lib_reloader.execute_if_updated
end
end
Sí, sé que es repugnante, pero es un truco. Puede haber una forma mejor de activar una recarga completa, pero esto funciona para mí. Mi caso de uso específico era una aplicación de Rack montada en una ruta de Rails, así que necesitaba volver a cargarla mientras trabajaba en su desarrollo.
Básicamente, lo que hace es verificar si los archivos en / lib han cambiado (fecha y hora modificada) desde la última vez que se cargó y luego activa una recarga si cambian.
También podría mencionar que tengo esto en mi config / application.rb
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]
Que de forma predeterminada se asegura de que se cargue todo en mi directorio lib.
¡Yays!
Tienes que agregar
config.autoload_paths += %W(#{config.root}/lib)
a su clase de aplicación en config / application.rb
https://rails.lighthouseapp.com/projects/8994/tickets/5218-rails-3-rc-does-not-autoload-from-lib
tenga en cuenta que en Rails 3 "load_once_paths" se convierte en "autoload_once_paths".
Además, parece que debería estar vacío a menos que explícitamente coloque algo en él.
Respuesta actualizada
Resumo todos mis hallazgos en mi blog, es mejor que mires allí:
- http://lsd4coders.muheimwebdesign.ch/2012/09/how-to-develop-rails-3-1-engines-with-ease-part-i-the-engine/
- http://lsd4coders.muheimwebdesign.ch/2012/09/how-to-develop-rails-3-1-engines-with-ease-part-ii-the-gem/
Respuesta anterior
Busqué una solución para esto también, y (para completar y también para señalar a otros en esta dirección) esto es lo que encontré.
A partir de Rails3.1, los motores se pueden generar fácilmente a través del rails plugin new my_plugin --full
command rails plugin new my_plugin --full
. Esto genera el esqueleto para un motor.
--full
significa que el motor se "fusionará" directamente con la aplicación incluida, de modo que, por ejemplo, los controladores deben ser accesibles directamente como si estuvieran definidos en la aplicación incluida. Esto le permite, por ejemplo, tener un archivo auxiliar en my_engine/app/helpers/my_helper.rb
que se combinará directamente en su app/helpers/my_helper.rb helper
.
Hay otra opción: --mountable
que crea un espacio de nombres para el motor para que sus controladores nunca colisionen con los de la aplicación. Esto da como resultado, por ejemplo, un ayudante en my_engine/app/helpers/my_engine/my_helper.rb
que no colisionará con una app/helpers/my_helper.rb
ayuda app/helpers/my_helper.rb
en su aplicación incluida.
Ahora la parte más interesante :
¡Dentro de la carpeta de test
del motor generado, hay una carpeta dummy
que contiene una aplicación completa de Rails! ¿Para qué es esto?
Cuando desarrolla un motor, sus funcionalidades deben funcionar por sí solas, y también debe probarse por sí solo. Por lo tanto, es la forma "incorrecta" de desarrollar un motor "dentro" de otra aplicación de Rails (aunque esto intuitivamente a menudo se sentirá bien al extraer funcionalidades existentes de una aplicación de Rails en un motor), y teóricamente tampoco es necesario volver a cargar el motor código con cada solicitud a la aplicación incluida.
La forma "correcta" parece ser la siguiente: desarrolla y prueba tu motor, como si fuera una aplicación completa de Rails que utiliza la aplicación dummy
. Allí puede hacer todo lo que puede hacer en cualquier aplicación Rails "normal", por ejemplo, crear controladores, modelos, vistas, etc. que utilizan las funcionalidades que el motor debe proporcionar. También puede iniciar normalmente un servidor utilizando los rails s
en su directorio de test/dummy
y acceder a la aplicación ficticia en localhost:3000
, y al ejecutar sus pruebas, la aplicación dummy
se utiliza automáticamente para las pruebas de integración. ¡Muy agradable! :-)
Tienes que tener cuidado de dónde poner tus cosas:
- Cualquier funcionalidad que esté destinada a ser utilizada en otra aplicación Rails entra en
my_engine/app
, mientras que cualquier funcionalidad que solo sea necesaria para probar la funcionalidad del motor entra entest/dummy/app
.
Luego puedes cargar fácilmente tu motor en el Gemfile
tu aplicación principal de la siguiente manera: gem ''my_engine'', :path => ''path/to/my_engine''
o publicarlo en GitHub como una gema.
(Una cosa interesante (y para volver al tema de este tema) es que cuando enciendo el servidor del dummy, ¡parece que todos los cambios en el motor se reflejan dentro! Así que de alguna manera parece ser posible incluir un motor dentro de un Rails aplicación sin guardarla en caché ...? No sé cómo sucede esto).
En resumen: un motor proporciona una funcionalidad que puede funcionar por sí solo, por lo que también debe desarrollarse y probarse por sí mismo. Luego, cuando ha alcanzado un estado estable, puede ser incluido por cualquier otra aplicación que necesite su funcionalidad.
Aquí hay algunos recursos que encuentro útiles:
Espero que encuentres útil esta respuesta. Todavía soy muy nuevo en los motores en general, así que si hay información incorrecta, por favor díganme, y la corregiré.
TL; DR
poner esto en config / application.rb
config.eager_load_paths += ["#{Rails.root}/lib"]
eliminar
require
declaraciones para sus archivos lib
¡Ir!
Déjame explicarte en detalle.
No sé por qué se acepta esta respuesta, ya que no ayuda con la recarga de la carpeta lib en cada solicitud . Primero pensé que funciona para Rails 2, pero la pregunta claramente establece que fue para Rails 3 y que la fecha de lanzamiento de 3.0.0 es anterior a la fecha de la respuesta.
Otras respuestas parecen demasiado complicadas o no proporcionan una solución real.
Decidí investigar un poco las cosas, porque me molestaba y hasta descubrí que las personas tienen una solución alternativa para esto y se trata de guardar archivos lib dentro de la app/models
en desarrollo y luego moverlos a /lib
cuando terminen. Podemos hacerlo mejor, ¿verdad?
Mi solución se prueba contra:
- Rieles 3.0.20
- Rieles 3.1.12
- Rieles 3.2.13
- Rails 4.0.0.rc1
Pon esto en tu config/application.rb
:
# in config/application.rb
config.eager_load_paths += ["#{Rails.root}/lib"]
¡Eso es!
Asegúrate de ponerlo aquí, ya que no funcionará si lo pones en config/environments/development.rb
, por ejemplo.
Asegúrese de que elimine todas las instrucciones require
para su código /lib
ya require
instrucciones require
también harán que esta solución no funcione.
Este código requiere implícitamente su código, por lo que si realiza comprobaciones de entorno (que son innecesarias) y en lugar del código anterior, decide escribir algo como esto:
# in config/application.rb
config.eager_load_paths += ["#{Rails.root}/lib"] if Rails.env.development?
debe tener cuidado con las declaraciones de require
, ya que todavía se requieren en todos los entornos sin desarrollo, en este escenario.
Por lo tanto, si aún decide hacer comprobaciones del entorno, asegúrese de realizar comprobaciones inversas para las declaraciones requeridas. De lo contrario, te morderán!
require "beer_creator" unless Rails.env.development?
También podría pensar que escribir un párrafo completo sobre algo que es innecesario también es innecesario, pero creo que también es necesario advertir a la gente sobre algo que es necesario cuando se hace algo innecesario.
Si desea obtener más información sobre este tema, consulte este pequeño tutorial .