Ich möchte in der Lage sein, von einer Controller-Aktion zu einer anderen bedingt zu senden, basierend auf einer Kombination von Abfrageparametern und Daten in der Datenbank.
Was ich gerade habe, ist etwas wie:
%Vor%Das funktioniert gut, aber es gibt eine HTTP-Umleitung aus, die langsam ist. Ich möchte in der Lage sein, dasselbe zu tun, aber innerhalb der gleichen HTTP-Anfrage.
Gibt es einen sauberen Weg, dies zu tun?
Bearbeiten: Das Kopfgeld wird an jemanden gehen, der mir einen sauberen Weg zeigt, dies zu tun, der die Controller und ihre Aktionen relativ unberührt lässt (außer dem Weiterleitungscode selbst).
Entpacken Sie den Code nicht in Aktionen, sondern extrahieren Sie den Code in lib / oder etwas und rufen Sie diesen Code von beiden Controllern auf.
%Vor%Ich vermute, dass Sie Option 3 wollen, aber lassen Sie uns zunächst einige Alternativen durchgehen
Option 1 - Schieben Sie die Controller-Auswahllogik in einen Helfer, der den richtigen Link in Ihre Ansicht einfügt. Vorteile - Controller bleiben sauber, Nachteile - wenn die Entscheidungslogik von den übergebenen Werten abhängt, wird dieser Ansatz nicht funktionieren. Wenn URL von externen Webseiten aufgerufen wird, funktioniert das nicht.
Option 2 - Schieben Sie die Logik zurück in Ihr Modell. Pro's - hält den Controller sauber. Nachteile - funktioniert nicht gut, wenn Sie viele sesson, params oder render / redirect_to Interaktion haben.
Option 3 - Bleiben Sie innerhalb desselben Controllers. Ich vermute, dass Sie versuchen, einige vorhandene Funktionalität durch einige neue Funktionalität zu ersetzen, aber nur in einigen Fällen. Pro's - Einfach und haben Zugriff auf alles, was Sie brauchen. Nachteile - funktioniert nur, wenn es sinnvoll ist, den gleichen Controller zu verwenden, d. H. Sie arbeiten mit derselben Entität wie Benutzer, Ort oder Firma.
Sehen wir uns ein Beispiel für Option 3 an. Mein Link-Controller hat ein völlig anderes Verhalten für Administratoren als andere Benutzer ...
%Vor%Wenn zwei Controller versuchen, dasselbe zu tun, gibt es eine sehr gute Chance, dass dies in einem Modell sein sollte. Schau dir dein Design gut an und - es tut mir leid, dass ich deine Erfahrung mit MVC nicht kenne - lies dünne Thin Controller-Techniken:
Wenn das Problem darin besteht, dass Sie den anderen Controller für das Rendern benötigen, dann sollte die Route zu Beginn vielleicht darauf zeigen, und trotzdem sollte die dünne Controller-Technik den Tag retten.
Wenn das Extrahieren des gemeinsamen Codes zwischen Controllern in einem Modul nicht für Sie funktioniert, würde ich Rack-Middleware verwenden. Ich habe keinen Code gesehen, der ActiveRecord
in Middleware verwendet, aber ich weiß nicht, warum das nicht möglich sein sollte, da Leute Redis
und ähnliches verwendet haben.
Sonst denke ich, Ihre einzige Option wäre, die Verarbeitung der Anfrage mit etwas wie (ungetestet, Pseudo-Beispiel) neu zu starten:
%Vor% Dies ist vergleichbar mit der Implementierung von Integrationstests. Aber ich weiß nicht, ob alles von call
, bis du einen Controller triffst, idempotent und sicher ist, so zu wiederholen. Sie könnten die Quelle verfolgen und sehen. Aber selbst wenn es jetzt in Ordnung ist, könnte es in jeder zukünftigen Version von Schienen oder Racks brechen.
Die Verwendung von Middleware würde dies vermeiden, indem Sie die Anforderung abfangen, bevor sie ausgeführt wurde. Sie sollten immer noch in der Lage sein, Code mit Ihrer Rails-Anwendung zu teilen, indem Sie ihn in gemeinsame Module extrahieren, die an beiden Stellen enthalten sind.
Ehrlich gesagt denke ich, dass es einfach sauberer ist, das einfache Controller-Code zu faktorisieren, aber es ist schwer, ohne die Details Ihrer Situation zu wissen, also dachte ich mir, ich würde das vorschlagen.
Tags und Links ruby-on-rails