Des rails:le filtre défini dans le fichier lib requis dans environnement.rb disparaît de filter_chain dans l'environnement de production.Pourquoi?

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

Question

Dans mon application Rails, j'ai un fichier dans lib qui, entre autres, configure un filtre qui s'exécute sur tous les contrôleurs.

Lors de l'exécution dans un environnement de développement, tout fonctionne bien.Cependant, en cours de production, le filtre disparaît.Ce qui est drôle, c'est qu'en inspectant le filter_chain, j'ai remarqué que d'autres filtres restent, par exemple.ceux définis dans les plugins, ou plus tard dans la classe de contrôleur spécifique.

J'ai testé cela avec Rails Edge et v2.3.0.

Mise à jour des tests :

J'ai maintenant testé avec des rails plus anciens et j'ai trouvé que le problème était présent dans la v2.1.0, mais pas dans la v2.0.5, je les ai divisés en deux et j'ai trouvé le 986aec5 les rails s'engagent à être coupables.


J'ai isolé le comportement du petit cas de test suivant :

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

Voici le résultat que j'obtiens lors de l'exécution sous le développement environnement:

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

Et voici le résultat du production environnement:

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

Comme mentionné précédemment, cela fonctionne bien pour n'importe quel environnement lorsque je fais la même chose via un plugin.Tout ce dont j'ai besoin c'est de mettre ce qu'il y a en dessous lib/foobar.rb dans le plugin init.rb déposer.

Donc, d'une certaine manière, j'ai déjà une solution de contournement, mais j'aimerais comprendre ce qui se passe et ce qui cause la disparition du filtre en production.

Je suppose que cela tient aux différentes manières dont Rails gère le chargement dans les différents environnements, mais je dois creuser plus profondément.

mise à jour

En effet, je l'ai maintenant réduit à la ligne de configuration suivante :

config.cache_classes = false

Si, dans production.rb, config.cache_classes est changé de true à false, l'application de test fonctionne correctement.

Je me demande toujours pourquoi le rechargement des classes provoque une telle chose.

Était-ce utile?

La solution

Frederick Cheung sur la la liste de messagerie avait la réponse :

  

Parce que cache_classes fait un peu plus que cela. Le chemin   avant que les filtres ne fonctionnent, si Foo < Bar alors seulement les filtres définis dans   Foo héritera de Bar à ce moment - en les ajoutant à Bar à un moment donné.   date ultérieure ne fera rien

     

En mode de développement, l'application démarre, votre fichier est requis, le filtre   ajouté à ActionController :: Base. Plus tard, la première demande arrive,   le contrôleur est chargé et il hérite de ce filtre.

     

Lorsque cache_classes a la valeur true, toutes vos classes d'application sont   chargé à l'avance. Cela se produit avant que votre fichier soit requis, donc   tous vos contrôleurs existent déjà lorsque ce fichier est exécuté et donc   n'a aucun effet. Vous pouvez résoudre ce problème en demandant ce fichier à un   initializer (s’assurer qu’il s’exécute avant le chargement des classes d’application), mais   vraiment pourquoi ne voudriez-vous pas simplement mettre cela dans application.rb?

     

Fred

Mon cas réel était bien plus complexe et voici comment j'ai trouvé le moyen de résoudre le problème:

config.after_initialize do
  require 'foobar'
end

Le bloc after_initialize est exécuté après l’initialisation de la structure mais avant le chargement des fichiers de l’application; par conséquent, il affectera ActionPack::Base une fois chargé, mais avant les contrôleurs d’application.

Je suppose que c'est le moyen généralement sûr de gérer tout le préchargement de la production.

Autres conseils

Déposez un script Ruby dans

RAILS_ROOT\config\initialiseurs

cela contient

require "foobar.rb"

Cela appelle le before_filter pour moi.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top