2010-08-06 15 views
41

Estoy en el proceso de refacturación de una lógica integrada en una aplicación de Rails en middleware, y una de las molestias con las que me he encontrado es una aparente falta de convención sobre dónde ubicarlas.¿Dónde coloca sus archivos de middleware Rack y requiere?

Actualmente me he decidido por app/middleware pero podría fácilmente moverlo a vendor/middleware o tal vez 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 si no recibo errores constantes no inicializados en las líneas config.middleware.use. Eso podría ser complicado muy rápidamente. Prefiero que esto esté guardado en un inicializador en alguna parte.

¿Hay un lugar convencional para poner esto?


La respuesta específica que estoy buscando con esta recompensa es: donde puedo poner las líneas requerir para que no se saturan el archivo environment.rb pero todavía se cargan antes de la config.middleware.use llamadas? Todo lo que he probado conduce a errores constantes no inicializados.


actualización: Ahora que estamos usando Rails 3.0, que tratar a una aplicación Rails como cualquier otra aplicación del estante; los archivos de código para middleware van en lib (o una gema listada en Gemfile) y se requieren y cargan en config.ru.

Respuesta

48

A partir de Rails 3.2, Rack middleware pertenece al directorio de la aplicación/middleware.

Funciona "out-of-the-box" sin ningún requerimiento explícito.

Ejemplo rápido:

estoy usando una clase middleware llamado CanonicalHost que se implementa en app/middleware/canonical_host.rb. He añadido la siguiente línea a production.rb (nota que la clase middleware se da de forma explícita, en lugar de como una cadena entre comillas, que funciona para cualquier archivos de configuración específicos del entorno):

config.middleware.use CanonicalHost, "example.com" 

Si está agregando middleware a application.rb, deberá incluir comillas, según @mltsy's comment.

config.middleware.use "CanonicalHost", "example.com" 
+0

Gracias, lo tendré en cuenta cuando actualizo. –

+4

¿Podría agregar algún enlace como referencia? No está funcionando de la caja para mí y las guías de Google/Rails no ayudan ... ¡gracias! – dgilperez

+0

Lo hice de manera inmediata, luego de darme cuenta de que había cometido el error de colocarlo en mi carpeta raíz en lugar de en la carpeta de la aplicación (ya especificada). Entonces, foo_app/app/middleware/file.rb. – d3vkit

0

No tengo conocimiento de una convención, pero ¿por qué no ponerla en el directorio /lib? Los archivos allí se cargan automáticamente por Rails.

+0

No hasta después de ejecutar environment.rb, si es que lo hace. Moverlos a lib no resolvió los errores constantes no inicializados. –

0

Puede crear un inicializador que requiera los archivos necesarios y luego dejar los archivos donde desee.

Según this, los inicializadores se ejecutan antes de cargar el middleware del rack.

+0

No. Aún obtener constante no inicializada. –

+0

Parece que estaba un poco optimista al leer eso. Supongo que config.ru no coincide con tus requisitos tampoco? – Jean

+0

bueno, eso requeriría el uso de rackup en lugar de script/servidor, ¿verdad? Podría hacerlo si tuviera que hacerlo, pero honestamente pensé que sería más fácil que esto. –

0

La solución de trabajo que tengo hasta ahora se está moviendo el middleware requiere a config/middleware.rb y requiriendo ese archivo en environment.rb, reduciéndolo a un solo requieren 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.

4

para los carriles 3:

#config/application.rb 
require 'lib/rack/my_adapter.rb' 
module MyApp 
    class Application < Rails::Application 
    config.middleware.use Rack::MyAdapter 
    end 
end 
23

Usted puede ponerlo en lib/tableized/file_name.rb. Siempre que la clase que está tratando de cargar sea detectable por su nombre de archivo, Rails cargará automáticamente el archivo necesario. Así, por ejemplo:

config.middleware.use "MyApp::TotallyAwesomeMiddleware" 

Se podría tener en:

lib/my_app/totally_awesome_middleware.rb 

rieles atrapa const_missing y attemts para cargar los archivos correspondientes a las constantes que faltan automáticamente. Solo asegúrate de que coincidan tus nombres y tu salsa.Carriles incluso proporciona ayudantes ingeniosas 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 cargan automáticamente cuando hacen referencia a él en el código.

+0

Tengo un middleware llamado 'Rack :: Backstage'. Ponlo en 'lib/rack/backstage.rb'.Error constante unitaria. –

+1

Esto funciona _only_ si el primer parámetro es una cadena. Una vez que lo descubrí, ¡éxito! –

+0

Solución fría. :) –

11

En mi Rails 3.2 aplicación, yo era capaz de conseguir mi carga middleware TrafficCop poniéndolo en app/middleware/traffic_cop.rb, tal como se describe @MikeJarema. Luego añade esta línea a mi config/application.rb, tal como se indica:

config.middleware.use TrafficCop 

Sin embargo, al inicio de la aplicación, seguí recibiendo este error:

uninitialized constant MyApp::Application::TrafficCop 

La especificación expresa el espacio de nombres raíz no ayudó tampoco:

config.middleware.use ::TrafficCop 
# uninitialized constant TrafficCop 

Por alguna razón (que todavía tengo que descubrir), en este punto en el ciclo de vida de los carriles, app/middleware no se incluyó en las rutas de carga. Si eliminé la línea config.middleware.use y ejecuté la consola, pude acceder a la constante TrafficCop sin ningún problema. Pero no pudo encontrarlo en app/middleware en el momento de la configuración.

que fija esta encerrando el nombre de la clase middleware entre comillas, así:

config.middleware.use "TrafficCop" 

De esta manera, evitaría el error uninitialized constant, ya que los carriles no está tratando de encontrar la clase TrafficCop por el momento. Pero cuando comienza a construir la pila de middleware, la cadena se mantendrá constante. En este momento, app/middleware se encuentra en las rutas de carga, por lo que la clase se cargará correctamente.

+0

Estoy en los carriles 3.2.18 y tengo el mismo problema cuando puse esto en application.rb, pero cuando lo puse en una configuración de entorno específica, ¡funcionó bien! Si sigue la ruta de carga comenzando con config.ru, resulta que application.rb se carga antes que la mayoría de las otras cosas, luego la aplicación se inicializa (que carga todos los inicializadores dinámicos, incluidos middlewares) y los otros archivos de entorno se cargan después eso, ¡entonces para entonces las constantes de middleware están definidas! – mltsy

Cuestiones relacionadas