Redirect_to richtig ausführen: Zurück in Ruby on Rails, wenn Referrer nicht verfügbar ist

91

Ich habe ein Problem mit redirect_to :back. Ja, es sind Überweiser.

Ich bekomme oft die Ausnahme

(ActionController :: RedirectBackError) "In der Anforderung für diese Aktion wurde kein HTTP_REFERER festgelegt, daher konnte redirect_to: back nicht erfolgreich aufgerufen werden. Wenn dies ein Test ist, müssen Sie request.env [\" HTTP_REFERER \ "] angeben."

Mir ist klar, dass dies darauf zurückzuführen ist, dass ein Referrer nicht verfügbar ist. Gibt es eine Möglichkeit, beispielsweise bei jedem Zugriff auf die zuletzt besuchte Seite eine Sitzungsvariable festzulegen und diese Sitzungsvariable zum Umleiten zu verwenden, wenn HTTP_REFERER nicht verfügbar ist?

user67050
quelle
Ich habe den gleichen Fehler in einer Aktualisierungsaktion, was seltsam ist, weil der Referrer nicht leer sein konnte (da die Anfrage von einem Formular stammen würde), aber einige Benutzer haben es gerade geschafft, was ich nicht weiß, wie.
Lulalala

Antworten:

144

Es ist unwahrscheinlich , dass Sie tun , um eine Sitzung haben und nicht einen Referrer haben.

Die Situation, dass ein Überweiser nicht eingestellt ist, ist nicht ungewöhnlich und ich rette normalerweise diese Erwartung:

def some_method
  redirect_to :back
rescue ActionController::RedirectBackError
  redirect_to root_path
end

Wenn Sie dies oft tun (was ich für eine schlechte Idee halte), können Sie es in eine andere Methode einwickeln, wie Maran vorschlägt.

Übrigens halte ich das für eine schlechte Idee, da dies den Benutzerfluss mehrdeutig macht. Nur bei einem Login ist dies sinnvoll.

UPDATE : Wie mehrere Personen betonten, funktioniert dies nicht mehr mit Rails 5. Stattdessen redirect_backunterstützt diese Methode auch einen Fallback. Der Code wird dann:

def some_method
  redirect_back fallback_location: root_path
end
Schaden
quelle
4
Ich vermute, dass ich dies ändern würde, um stattdessen recovery_from zu verwenden.
Bob Aman
1
@ BobAman IMO könnten wir verwenden, rescue_fromwenn der Controller mehrere hatteredirect_to :back
Theo B
funktioniert nicht mit Rails 5, ActionController :: RedirectBackError ist undefiniert ... welche Lösung?
Matrix
Verwenden Sie stattdessen:redirect_to (request.referrer || root_url)
Abhi
38

Hier ist meine kleine Methode redirect_to_back:

  def redirect_to_back(default = root_url)
    if request.env["HTTP_REFERER"].present? and request.env["HTTP_REFERER"] != request.env["REQUEST_URI"]
      redirect_to :back
    else
      redirect_to default
    end
  end

Sie können eine optionale URL übergeben, um an eine andere Stelle zu gelangen, wenn http_refferrer leer ist.

Mirko
quelle
37
def store_location
  session[:return_to] = request.request_uri
end

def redirect_back_or_default(default)
  redirect_to(session[:return_to] || default)
  session[:return_to] = nil
end

Versuch das! (Dank dem Authlogic Plugin)

Maran
quelle
22
Dies ist eine gute Lösung, aber ich möchte jeden, der sie verwendet, dringend bitten, sich vor Augen zu halten, dass sie auf eine für den Benutzer äußerst verwirrende Weise "kaputt gehen" kann, wenn er oder sie mehrere Registerkarten zum Durchsuchen Ihrer App verwendet.
Mitch Lindgren
3
+1 Zur Beantwortung der Frage und ohne Kritik an Entwurfsmethoden.
Abe Petrillo
31

Kernfunktion

redirect_back ist eine Kernfunktion von Rails 5+ und ist in der verfügbar ActionController::Redirecting Modul enthalten, das bereits in enthalten ist ApplicationController::Base.

DEPRECATION WARNING: redirect_to :backist veraltet und wird von Rails 5.1 entfernt. Benutzen Sie bitteredirect_back(fallback_location: fallback_location) where, fallback_locationum den zu verwendenden Speicherort darzustellen, wenn die Anforderung keine HTTP-Verweisinformationen enthält.

EDIT: Quelle

Cyril Duchon-Doris
quelle
Link zur Quelle, bitte
Chris Bloom
1
@ Chrisbloom7 Dies ist eine Warnmeldung, die ich beim Ausführen von Rails 5.0.0beta3 mit hatte redirect_to :back.
Cyril Duchon-Doris
21

Vielleicht ist es spät, aber ich möchte meine Methode teilen, bei der auch Optionen erhalten bleiben:

  def redirect_back_or_default(default = root_path, *options)
    tag_options = {}
    options.first.each { |k,v| tag_options[k] = v } unless options.empty?
    redirect_to (request.referer.present? ? :back : default), tag_options
  end

Sie können es verwenden wie:

redirect_back_or_default(some_path, :notice => 'Hello from redirect', :status => 301)
troex
quelle
13

Fügen Sie dies ähnlich wie bei der Antwort von @ troex Ihrem Anwendungscontroller hinzu

def redirect_back_or_default(default = root_path, options = {})
  redirect_to (request.referer.present? ? :back : default), options
end

Verwenden Sie es dann in Ihrem Controller

redirect_back_or_default answer_path(answer), flash: { error: I18n.t('m.errors')}
longkt90
quelle
0

Vor kurzem bin ich auf dasselbe Problem gestoßen, bei dem ich entweder umleiten musste :backoder zu einer bestimmten Seite. Nachdem ich viele Lösungen gefunden hatte, fand ich schließlich diese, die einfach ist und das Problem zu lösen scheint:


if request.env["HTTP_REFERER"].present?
    redirect_to :back
else
    redirect_to 'specific/page'
end

Wenn Sie sessionDetails verwenden möchten , tun Sie dies im else-Teil des Codes.

Rahul Goyal
quelle