ruby on rails - apps - ¿Dónde colocas tus archivos de middleware de Rack y necesitas?
ruby rack (7)
Estoy en el proceso de refactorizar parte de la lógica incorporada en una aplicación Rails en el middleware, y una de las molestias con las que me he topado es una aparente falta de convención sobre dónde colocarlas.
Actualmente me he decidido por la app/middleware
pero podría moverlo fácilmente al vendor/middleware
o tal vez al vendor/plugins/middleware
...
El mayor problema es tener que requerir los archivos individuales en la parte superior de config/environment.rb
require "app/middleware/system_message"
require "app/middleware/rack_backstage"
o de lo contrario obtengo errores constantes sin inicializar en las líneas config.middleware.use
. Eso podría ensuciarse muy rápidamente. Preferiría que esto estuviera escondido en un inicializador en alguna parte.
¿Hay un lugar convencional para poner esto?
La respuesta específica que busco con esta recompensa es: ¿ dónde puedo colocar las líneas requeridas para que no saturen el archivo environment.rb pero aún así se carguen antes de las llamadas config.middleware.use? Todo lo que he intentado conduce a errores constantes sin inicializar.
Actualización : ahora que estamos usando Rails 3.0, trato una aplicación Rails como cualquier otra aplicación Rack; Los archivos de código para middleware van en lib
(o una gema que se encuentra en Gemfile
) y son necesarios y cargados en config.ru
.
A partir de Rails 3.2, Rack middleware pertenece al directorio app / middleware.
Funciona "fuera de la caja" sin ningún requisito explícito.
Ejemplo rápido:
Estoy usando una clase de middleware llamada CanonicalHost que se implementa en app / middleware / canonical_host.rb . He agregado la siguiente línea a production.rb ( tenga en cuenta que la clase de middleware está dada explícitamente, en lugar de como una cadena entre comillas, que funciona para cualquier archivo de configuración específico del entorno):
config.middleware.use CanonicalHost, "example.com"
Si está agregando middleware a application.rb , deberá incluir citas, según el comentario de @ mltsy .
config.middleware.use "CanonicalHost", "example.com"
En mi aplicación Rails 3.2, pude cargar mi middleware TrafficCop
colocándolo en app/middleware/traffic_cop.rb
, tal como se describe en @MikeJarema. Luego agregué esta línea a mi config/application.rb
, como se indica:
config.middleware.use TrafficCop
Sin embargo, al iniciar la aplicación, seguí recibiendo este error:
uninitialized constant MyApp::Application::TrafficCop
Especificar explícitamente el espacio de nombres de la raíz tampoco ayudó:
config.middleware.use ::TrafficCop
# uninitialized constant TrafficCop
Por alguna razón (que aún no he descubierto), en este punto del ciclo de vida de Rails, la app/middleware
no estaba incluida en las rutas de carga. Si quito la línea config.middleware.use
y ejecuté la consola, podría acceder a la constante TrafficCop
sin ningún problema. Pero no pudo encontrarlo en la app/middleware
en el momento de la configuración.
Arreglé esto encerrando el nombre de la clase de middleware entre comillas, así:
config.middleware.use "TrafficCop"
De esta manera, evitaría el error uninitialized constant
, ya que Rails no está tratando de encontrar la clase TrafficCop
todavía. Pero, cuando comienza a construir la pila de middleware, se va a constatar la cadena. En este momento, la app/middleware
está en las rutas de carga, por lo que la clase se cargará correctamente.
La solución de trabajo que tengo hasta ahora es mover el middleware requerido a config/middleware.rb
y requerir ese archivo en environment.rb
, reduciéndolo a un solo requisito con el que puedo vivir.
Todavía me gustaría escuchar cómo otras personas han resuelto este problema aparentemente básico de agregar middleware a Rails.
No estoy al tanto de una convención, pero ¿por qué no ponerla en el directorio /lib
? Los archivos allí se cargan automáticamente por Rails.
Para rieles 3:
#config/application.rb
require ''lib/rack/my_adapter.rb''
module MyApp
class Application < Rails::Application
config.middleware.use Rack::MyAdapter
end
end
Podría crear un inicializador que requiera los archivos necesarios y luego dejar los archivos donde desee.
De acuerdo con this los inicializadores se ejecutan antes de que se cargue el middleware de rack.
Puedes ponerlo en lib/tableized/file_name.rb
. Mientras la clase que está intentando cargar sea visible por su nombre de archivo, Rails cargará automáticamente el archivo necesario. Así por ejemplo:
config.middleware.use "MyApp::TotallyAwesomeMiddleware"
Te mantendrías en:
lib/my_app/totally_awesome_middleware.rb
Rails atrapa const_missing y trata de cargar archivos correspondientes a las constantes faltantes automáticamente. Solo asegúrate de que tus nombres coincidan y estarás listo. Rails incluso proporciona ayudantes ingeniosos que te ayudarán a identificar la ruta de un archivo fácilmente:
>> ChrisHeald::StdLib.to_s.tableize.singularize
=> "chris_heald/std_lib"
Así que mi stdlib vive en lib/chris_heald/std_lib.rb
, y se carga automáticamente cuando hago referencia en el código.