Wie leite ich zur vorherigen Seite in Ruby On Rails um?


186

Ich habe eine Seite, die alle Projekte auflistet, die sortierbare Überschriften und Paginierungen haben.

path:
/projects?order=asc&page=3&sort=code

Ich beschließe, eines der Projekte zu bearbeiten

path:
projects/436/edit

Wenn ich auf dieser Seite auf Speichern klicke, wird die Projektcontroller- / Aktualisierungsmethode aufgerufen. Nachdem ich den Code aktualisiert habe, möchte ich zu dem Pfad umleiten, auf dem ich war, bevor ich auf Bearbeiten eines bestimmten Projekts geklickt habe. Mit anderen Worten, ich möchte mit derselben Sortierung auf derselben Seite sein.

Ich habe link_to (: back) gesehen und dachte, dass: back in redirect_to (: back) funktionieren könnte, aber das geht nicht.

puts YAML::dump(:back) 
yields the following:
:back 

Irgendwelche Ideen, wie ich das zum Laufen bringen könnte. Es scheint ein Problem zu sein, das leicht zu lösen wäre, aber ich bin neu bei RoR.

Antworten:


323

Speichern Sie in Ihrer Bearbeitungsaktion die anfordernde URL im Sitzungs-Hash, der für mehrere Anforderungen verfügbar ist:

session[:return_to] ||= request.referer

Leiten Sie dann nach erfolgreichem Speichern in Ihrer Update-Aktion darauf um:

redirect_to session.delete(:return_to)

68
Ich würde redirect_to session.delete(:return_to)in der Update-Aktion vorschlagen . Dadurch wird der Wert aus der Sitzung bereinigt, da er nicht mehr benötigt wird.
Stigi

19
Verwechselt nicht das Öffnen mehrerer Registerkarten diese Logik?
Jones

12
Könntest du nicht einfach redirect_to request.referer?
Elle Mundy

1
@DanMundy Nein, damit es funktioniert, sollte es sein request.referer.referer, wenn das möglich sein könnte. @ Jaime Bellmyer Warum ||=?
X-Yuri

@ Jones ja. Es gibt auch Verwirrung, wenn Sie zu einer anderen Modellbearbeitung wechseln. Mich interessiert auch, warum || =
Mauro

99

Warum funktioniert es redirect_to(:back)nicht für Sie, warum ist es ein No Go?

redirect_to(:back)wirkt wie ein Zauber für mich. Es ist nur eine Abkürzung für redirect_to(request.env['HTTP_REFERER'])

http://apidock.com/rails/ActionController/Base/redirect_to (vor Rails 3) oder http://apidock.com/rails/ActionController/Redirecting/redirect_to (Rails 3)

Bitte beachten Sie, dass redirect_to(:back)dies in Rails 5 veraltet ist. Sie können verwenden

redirect_back(fallback_location: 'something')stattdessen (siehe http://blog.bigbinary.com/2016/02/29/rails-5-improves-redirect_to_back-with-redirect-back.html )


12
redirect_to :backfunktioniert auch bei mir nicht gut, sagen wir Sie besuchen /posts/new, dies wird als Referer für die nächste Anfrage festgelegt, so dass nach erfolgreicher Übermittlung des Formulars das Formular erneut angezeigt wird, d /posts/new. h . Es funktioniert jedoch gut für andere Zwecke.
Kris

Das heißt, OP möchte zweimal zurückleiten. Ich wette, er könnte es einfach redirect_to projects_path.
X-Yuri

Ja. redirect_back funktioniert nicht so gut in Rails 5
strizzwald

@strizzwald was bedeutet "funktioniert nicht gut"? Irgendwelche Details?
Pascal

@pascalbetz, Was ich damit gemeint habe ist, dass Sie in diesem Fall aus dieser Ausnahme retten müssten , wenn dies HTTP_REFERERnicht festgelegt ist ActionController::RedirectBackError. Nach meinem Verständnis redirect_backerfordert die Verwendung keine Ausnahmebehandlung, da Sie zur Bereitstellung gezwungen sind fallback_location. Vielleicht ist "funktioniert nicht gut" nicht der richtige Weg, um es auszudrücken.
Strizzwald

45

Ich mag Jaimes Methode mit einer Ausnahme, es hat für mich besser funktioniert, den Referer jedes Mal neu zu speichern:

def edit
    session[:return_to] = request.referer
...

Der Grund dafür ist, dass Sie beim Bearbeiten mehrerer Objekte immer wieder zu der ersten URL umgeleitet werden, die Sie mit Jaimes Methode in der Sitzung gespeichert haben. Nehmen wir zum Beispiel an, ich habe Objekte von Apple und Orange. Ich bearbeite Apple und werde session[:return_to]auf den Referer dieser Aktion eingestellt. Wenn ich Orangen mit demselben Code bearbeite, session[:return_to]wird er nicht festgelegt, da er bereits definiert ist. Wenn ich die Orange aktualisiere, werde ich an den Referer der vorherigen Apple # -Bearbeitungsaktion gesendet.


Ja, aber können Sie vorschlagen, was zu tun ist, wenn versehentlich dieselbe URL gespeichert wurde, unter der Sie sich befinden? Du bist bei Apple und du kommst von Apple. Und Sie wollen vorherigen Standort
Uko

33

So machen wir es in unserer Anwendung

def store_location
  session[:return_to] = request.fullpath if request.get? and controller_name != "user_sessions" and controller_name != "sessions"
end

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

Auf diese Weise speichern Sie nur die letzte GET-Anforderung im :return_toSitzungsparameter, sodass alle Formulare, auch wenn POSTed mehrmals verwendet wird, funktionieren :return_to.


3
request.request_uriist nicht mehr verfügbar, daher schlage ich vor, request.fullpathstattdessen zu verwenden
anka

@anka Aktualisiert. Vielen Dank für den Kommentar
MBO

2
Ja, das ist ziemlich gut. Ich würde nur vorschlagen, generell nicht andund orin ifAussagen zu verwenden. Verwenden Sie &&und ||stattdessen. Details hier .
Achilles

19

In Rails 5 können Sie gemäß den Anweisungen in Rails Guides Folgendes verwenden:

redirect_back(fallback_location: root_path)

Der 'Back'-Speicherort wird aus dem HTTP_REFERER-Header abgerufen, der vom Browser nicht garantiert festgelegt wird. Deshalb sollten Sie einen 'fallback_location' angeben.


Diese Funktion erscheint in Schienen 5.
Chambeur

@pSkarl Wie kann ich ein noticeObjekt mit der redirect_backAnweisung übergeben, um dem Benutzer mitzuteilen, dass mit einer Flash-Nachricht ein Fehler aufgetreten ist ?
Alexventuraio

2
Nun, ich könnte das lösen, indem ich : redirect_back(fallback_location: root_path, notice: "Something went wrong!"). Hoffe es könnte irgendwie helfen.
Alexventuraio

18

request.referer wird von Rack eingestellt und wie folgt eingestellt:

def referer
  @env['HTTP_REFERER'] || '/'
end

Tun Sie einfach ein redirect_to request.refererund es wird immer auf die wahre verweisenden Seite, oder die root_path ( ‚/‘ umzuleiten. Dies ist wichtig, wenn Sie Tests, die bei Direktnavigation fehlschlagen, an eine bestimmte Seite übergeben, auf der der Controller ein redirect_to: back auslöst


Nicht sicher , welche Datei , die Sie suchen auf , aber an der Rack - Quelle wird diese , wie refererwurde als definierter 28. März 2011 , und das ist , wie es ab definiert ist heute . Das heißt, || '/'ist nicht Teil der Definition.
Maček

1

Für diejenigen, die interessiert sind, ist hier meine Implementierung, die die ursprüngliche Antwort von MBO erweitert (geschrieben gegen Rails 4.2.4, Ruby 2.1.5).

class ApplicationController < ActionController::Base
  after_filter :set_return_to_location

  REDIRECT_CONTROLLER_BLACKLIST = %w(
    sessions
    user_sessions
    ...
    etc.
  )

  ...

  def set_return_to_location
    return unless request.get?
    return unless request.format.html?
    return unless %w(show index edit).include?(params[:action])
    return if REDIRECT_CONTROLLER_BLACKLIST.include?(controller_name)
    session[:return_to] = request.fullpath
  end

  def redirect_back_or_default(default_path = root_path)
    redirect_to(
      session[:return_to].present? && session[:return_to] != request.fullpath ?
        session[:return_to] : default_path
    )
  end
end
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.