Rails: Filter in der in der Umgebung erforderlichen LIB -Datei definiert. RB verschwindet aus filter_chain in der Produktionsumgebung. Wieso den?

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

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.

War es hilfreich?

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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top