Trilhos:o filtro definido no arquivo lib exigido em Environment.rb desaparece de filter_chain no ambiente de produção.Por que?

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

Pergunta

Na minha aplicação Rails, tenho um arquivo em lib que, entre outras coisas, configura um filtro que roda em todos os controladores.

Ao executar em ambiente de desenvolvimento, tudo funciona bem.No entanto, em produção, o filtro desaparece.O engraçado é que, ao inspecionar o filter_chain, notei que outros filtros permanecem, por exemplo.aqueles definidos em plug-ins ou posteriormente na classe de controlador específica.

Eu testei isso com Rails Edge e v2.3.0.

Atualização de teste:

Agora testei com trilhos mais antigos e descobri que o problema estava presente na v2.1.0, mas não na v2.0.5, eu os dividi ao meio e encontrei o 986aec5 Rails se compromete a ser culpado.


Isolei o comportamento para o seguinte pequeno caso de teste:

# 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'

Aqui está a saída que recebo ao executar sob o desenvolvimento ambiente:

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

E aqui está a saída para o Produção ambiente:

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

Como mencionado anteriormente, funciona bem em qualquer ambiente quando faço a mesma coisa via plugin.Tudo que eu preciso é colocar o que está embaixo lib/foobar.rb no plugin init.rb arquivo.

De certa forma, já tenho uma solução alternativa, mas gostaria de entender o que está acontecendo e o que está causando a falta do filtro durante a produção.

Suponho que seja algo nas diferentes maneiras como o Rails lida com o carregamento em diferentes ambientes, mas preciso me aprofundar.

atualizar

Na verdade, agora reduzi-o à seguinte linha de configuração:

config.cache_classes = false

Se, em production.rb, config.cache_classes é alterado de true para false, o aplicativo de teste funcionará corretamente.

Ainda me pergunto por que o recarregamento da classe está causando tal coisa.

Foi útil?

Solução

Frederick Cheung no Lista de trilhos tive a resposta:

Porque cache_classes faz um pouco mais do que isso.O caminho antes dos filtros funcionar, se Foo <bar, ​​apenas os filtros definidos em bar naquele ponto serão herdados por Foo - adicionando -os à barra posteriormente não fará nada

No modo de desenvolvimento, o aplicativo é iniciado, seu arquivo é necessário, o filtro adicionado ao ActionController :: Base.Mais tarde, a primeira solicitação aparece, o controlador é carregado e herda esse filtro.

Quando o cache_classes é verdadeiro, todas as suas classes de aplicativos são carregadas com antecedência.Isso acontece antes que seu arquivo seja necessário; portanto, todos os seus controladores já existem quando esse arquivo é executado e, portanto, não tem efeito.Você pode resolver isso exigindo esse arquivo de um inicializador (garantindo que ele seja executado antes que as classes de aplicativos sejam carregadas), mas realmente por que você não colocaria isso no application.rb?

Fred


Meu caso real era bem mais complicado, e foi assim que encontrei para resolver o problema:

config.after_initialize do
  require 'foobar'
end

O after_initialize O bloco é executado após a inicialização da estrutura, mas antes de carregar os arquivos do aplicativo, portanto, afetará ActionPack::Base depois de ter sido carregado, mas antes dos controladores do aplicativo.

Acho que essa é a maneira geralmente segura de lidar com todo o pré-carregamento que ocorre na produção.

Outras dicas

Solte um script de rubi em

Rails_root Config Inicializadores

Isso contém

require "foobar.rb"

Isso chama o antes_filter para mim.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top