So finden Sie die aktuelle abstrakte Route in Rails Middware

8

Schienenversion: '~ & gt; 4.2.7.1 '

Spree-Version: '3.1.1'

TlDr: Wie bekomme ich Route als /api/products/:id oder Controller und Aktion dieser Route in einer Middleware von Rails 4 Anwendung.

Details:

Ich füge eine Middleware in meine Rails App ein, die ähnlich wie scout_statsd_rack ist. Dies fügt die folgende zur App hinzu, um Messwerte über statsd zu senden:

%Vor%

Ich möchte die aktuelle Route in der Middleware finden, damit ich für jede Route spezifische Metriken senden kann.

Ich habe den Ansatz versucht hier , das env['PATH_INFO'] angibt, kann Pfad angeben, was es tut, aber es gibt mit URL-Parametern wie folgt: /api/products/4 , aber was ich will, ist /api/products/:id , da mein Ziel die Leistung von /api/products/:id API.

env['REQUEST_PATH'] und env['REQUEST_URI'] gibt auch die gleiche Antwort.

Ich habe versucht, hier zu antworten und hier :

%Vor%

oder wie das

%Vor%

Aber es gab folgenden Fehler:

  

NoMethodError (undefinierte Methode path_info' for {"path_info"=>"/api/v1/products/4"}:Hash):
vendor/bundle/gems/actionpack-4.2.7.1/lib/action_dispatch/journey/router.rb:100:in
find_routes '
  vendor / bundle / edelsteine ​​/ actionpack-4.2.7.1 / lib / action_dispatch / journey / router.rb: 59: in recognize'
vendor/bundle/gems/scout_statsd_rack-0.1.7/lib/scout_statsd_rack.rb:27:in
call '

Diese Antwort behandelt request.original_url , aber wie greife ich auf die Variable request zu, denke ich, dass sie gleich sein sollte als env , aber nicht in der Lage, Route als Wille von diesem zu erhalten.

Bearbeiten # 1

Sie können das Beispiel-Repo hier sehen, mit dem Code der Rails-Middleware hier , das Einrichten kann wie in README und dann kann diese API erreicht werden: http://localhost:3000/api/v1/products/1 .

Bearbeiten # 2

Ich habe versucht, die Vorgehensweise von @ MichałMłoźniak wie folgt zu verwenden:

%Vor%

Aber ich habe folgende Antwort:

%Vor%

Ich habe die Änderungen auch hier gepusht >.

    
Saurabh 09.03.2017, 09:40
quelle

1 Antwort

8

Sie müssen ActionDispatch::Request oder Rack::Request an recognize method übergeben. Hier ist ein Beispiel aus einer anderen App:

%Vor%

Das Gleiche funktioniert mit ActionDispatch::Request . Innerhalb der Middleware können Sie dieses Objekt einfach erstellen:

%Vor%

Und wenn Sie mehr Informationen über die erkannte Route benötigen, können Sie in das route-Objekt schauen, das durch recognize method zum Blockieren gebracht wurde.

Aktualisieren

Die obige Lösung wird für normale Rails-Routen funktionieren, aber da Sie nur eine Spree-Engine installiert haben, müssen Sie eine andere Klasse verwenden

%Vor%

Ich denke, das Beste wäre, eine generische Lösung zu finden, die mit jeder Kombination aus normalen Routen und Engines funktioniert, aber das wird in Ihrem Fall funktionieren.

Update # 2

Für eine allgemeinere Lösung müssen Sie sich die Quelle des Rails-Routers ansehen, die Sie in ActionDispatch module finden. Schauen Sie sich die Module Routing und Journey an. Was ich herausgefunden habe ist, dass die zurückgegebene Route von recognize Methode getestet werden kann, ob dies ein Dispatcher ist oder nicht.

%Vor%

Dieser Ansatz funktioniert im Falle Ihrer App, wird aber nicht allgemein sein. Wenn Sie beispielsweise sidekiq installiert haben, wird route.app.app Sidekiq::Web sein, so dass es anders behandelt werden muss. Um eine allgemeine Lösung zu haben, müssen Sie alle möglichen montierbaren Engines handhaben, die der Rails Router unterstützt.

Ich denke, es ist besser, etwas zu bauen, das alle Ihre Fälle in der aktuellen Anwendung abdecken wird. Die Sache, an die man sich erinnern sollte, ist, dass der Wert von route , der an Schwarz ausgegeben wird, ein Dispatcher sein kann oder nicht, wenn die anfängliche Anfrage erkannt wird. Wenn dies der Fall ist, haben Sie eine normale Rails-Route, falls nicht, müssen Sie eine rekursive Prüfung durchführen.

    
Michał Młoźniak 13.03.2017, 23:25
quelle