Rieles:El filtro definido en el archivo lib requerido en Environment.rb desaparece de filter_chain en el entorno de producción.¿Por qué?

StackOverflow https://stackoverflow.com/questions/620146

Pregunta

En mi aplicación Rails, tengo un archivo en lib que, entre otras cosas, configura un filtro que se ejecuta en todos los controladores.

Cuando se ejecuta en un entorno de desarrollo, todo funciona bien.Sin embargo, durante el proceso de producción el filtro desaparece.Lo curioso es que, al inspeccionar el filter_chain, Noté que permanecen otros filtros, por ejemplo.aquellos definidos en complementos, o más adelante en la clase de controlador específica.

Probé esto tanto con Rails Edge como con v2.3.0.

Actualización de prueba:

Ahora probé con rieles más antiguos y descubrí que el problema estaba presente en la versión 2.1.0, pero no en la versión 2.0.5, los dividí en dos y encontré el 986aec5 Rails se compromete a ser culpable.


He aislado el comportamiento en el siguiente pequeño caso de prueba:

# app/controllers/foo_controller.rb
class FooController < ApplicationController
  def index
    render :text => 'not filtered'
  end
end

# lib/foobar.rb
ActionController::Base.class_eval do
  before_filter :foobar
  def foobar
    render :text => 'hi from foobar filter'
  end
end

# config/environment.rb (at end of file)
require 'foobar'

Aquí está el resultado que obtengo cuando ejecuto bajo el desarrollo ambiente:

$ script/server &
$ curl localhost:3000/foo
> hi from foobar filter

Y aquí está el resultado del producción ambiente:

$ script/server -e production &
$ curl localhost:3000/foo             
> not filtered

Como se mencionó anteriormente, funciona bien en cualquier entorno cuando hago lo mismo mediante un complemento.Todo lo que necesito es poner lo que hay debajo lib/foobar.rb en el complemento init.rb archivo.

Entonces, en cierto modo, ya tengo una solución alternativa, pero me gustaría entender qué está pasando y qué está causando que el filtro desaparezca cuando está en producción.

Supongo que se debe a las diferentes formas en que Rails maneja la carga en los diferentes entornos, pero necesito profundizar más.

actualizar

De hecho, ahora lo he reducido a la siguiente línea de configuración:

config.cache_classes = false

Si, en production.rb, config.cache_classes se cambia de true a false, la aplicación de prueba funciona correctamente.

Todavía me pregunto por qué la recarga de clases está causando tal cosa.

¿Fue útil?

Solución

Frederick Cheung en la Lista de rieles tenía la respuesta :

  

Porque cache_classes hace un poco más que eso. La manera   antes de que funcionen los filtros, si Foo < Barra entonces solo aquellos filtros definidos en   La barra en ese punto será heredada por Foo, agregándola a la barra en un   una fecha posterior no hará nada

     

En el modo de desarrollo, se inicia la aplicación, se requiere su archivo, el filtro   agregado a ActionController :: Base. Más tarde llega la primera solicitud,   el controlador se carga y hereda ese filtro.

     

Cuando cache_classes es verdadero, todas sus clases de aplicación son   cargado de antemano. Esto sucede antes de que se requiera su archivo, así que   todos sus controladores ya existen cuando se ejecuta ese archivo y por lo tanto   no tiene efecto. Puede resolver esto requiriendo este archivo de un   inicializador (asegurándose de que se ejecuta antes de cargar las clases de la aplicación), pero   ¿Por qué no lo pondrías en application.rb?

     

Fred


Mi caso real fue mucho más complicado, y esta es la forma en que encontré para resolver el problema:

config.after_initialize do
  require 'foobar'
end

El bloque after_initialize se ejecuta después de que se haya inicializado el marco pero antes de que cargue los archivos de la aplicación, por lo tanto, afectará a ActionPack::Base después de que se haya cargado, pero antes de que lo estén los controladores de la aplicación.

Supongo que esa es la forma generalmente segura de lidiar con toda la precarga que se produce en la producción.

Otros consejos

Coloca un script Ruby en

RAILS_ROOT\config\inicializadores

eso contiene

require "foobar.rb"

Esto invoca el before_filter por mí.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top