Rails: Filter in der in der Umgebung erforderlichen LIB -Datei definiert. RB verschwindet aus filter_chain in der Produktionsumgebung. Wieso den?
-
03-07-2019 - |
Frage
In meiner Rails -Anwendung habe ich eine Datei in Lib, die unter anderem einen Filter einsetzt, der auf allen Controllern ausgeführt wird.
Wenn Sie in der Entwicklungsumgebung laufen, läuft alles gut. In der Produktion wird jedoch der Filter gefehlt. Die lustige Sache ist, indem man die inspiziert filter_chain
, Ich bemerkte, dass andere Filter verbleiben, z. Die in Plugins oder später in der spezifischen Controller -Klasse definierten.
Ich habe dies sowohl mit Rails Edge als auch v2.3.0 getestet.
Testen von Update:
Ich habe jetzt mit älteren Schienen getestet und festgestellt, dass das Problem auf V2.1.0 zurückzuführen ist, aber nicht in V2.0.5, habe ich sie halbiert und die gefunden 986aec5 Rails verpflichten sich, schuldig zu sein.
Ich habe das Verhalten auf den folgenden winzigen Testfall isoliert:
# 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'
Hier ist die Ausgabe, die ich beim Laufen unter dem bekomme Entwicklung Umgebung:
$ script/server &
$ curl localhost:3000/foo
> hi from foobar filter
Und hier ist die Ausgabe für die Produktion Umgebung:
$ script/server -e production &
$ curl localhost:3000/foo
> not filtered
Wie zuvor angedeutet, funktioniert es für jede Umgebung gut, wenn ich das Gleiche über Plugin mache. Alles was ich brauche ist zu platzieren, was unter sich geht lib/foobar.rb
im Plugin's init.rb
Datei.
In gewisser Weise habe ich bereits eine Problemumgehung, aber ich würde gerne verstehen, was los ist und was der Filter in der Produktion verschwindet.
Ich vermute, es ist etwas auf die unterschiedliche Art und Weise, wie Rails das Laden in den verschiedenen Umgebungen behandelt, aber ich muss tiefer graben.
aktualisieren
In der Tat habe ich es jetzt auf die folgende Konfigurationslinie eingegrenzt:
config.cache_classes = false
Wenn, in production.rb
, config.cache_classes
wird von true
zu false
, Die Testanwendung funktioniert ordnungsgemäß.
Ich frage mich immer noch, warum das Nachladen der Klasse so etwas verursacht.
Lösung
Frederick Cheung auf der Rails -Liste hatte die Antwort:
Weil Cache_classes etwas mehr als nur das tut. Der Weg vor Filtern funktioniert, wenn Foo <bar baly nur die in der Bar definierten Filter zu diesem Zeitpunkt von Foo vererbt werden, wird es nichts tun
Im Entwicklungsmodus startet die App, Ihre Datei ist erforderlich, der Filter zum ActionController :: Base hinzugefügt. Später kommt die erste Anfrage auf, der Controller wird geladen und erbt diesen Filter.
Wenn Cache_classes wahr ist, werden alle Ihre Anwendungsklassen im Voraus geladen. Dies geschieht, bevor Ihre Datei erforderlich ist, sodass alle Ihre Controller bereits vorhanden sind, wenn diese Datei ausgeführt wird, und sie hat daher keinen Einfluss. Sie könnten dies lösen, indem Sie diese Datei von einem Initialisierer benötigen (um sicherzustellen, dass sie vor dem geladenen App -Klassen ausgeführt wird).
Fred
Mein eigentlicher Fall war tatsächlich viel besser involviert, und so fand ich das Problem:
config.after_initialize do
require 'foobar'
end
Das after_initialize
Block läuft nach der Initialisierung des Framework ActionPack::Base
Nachdem es geladen wurde, aber vor den Anwendungscontrollern.
Ich denke, das ist der allgemein sichere Weg, um mit all dem Vorladen umzugehen, die in der Produktion vorhanden sind.
Andere Tipps
Lassen Sie ein Ruby -Skript ein
Rails_root config Initializer
das beinhaltet
require "foobar.rb"
Dies ruft den Vorabendfilter für mich auf.