Come reindirizzare alla pagina precedente in Ruby On Rails?


186

Ho una pagina che elenca tutti i progetti con intestazioni e impaginazione ordinabili.

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

Ho scelto di modificare uno dei progetti

path:
projects/436/edit

Quando faccio clic su Salva su quella pagina, chiama il controller / il metodo di aggiornamento dei progetti. Dopo aver aggiornato il codice, voglio reindirizzare al percorso in cui mi trovavo prima di fare clic su Modifica un progetto specifico. In altre parole, voglio essere sulla stessa pagina con lo stesso ordinamento.

Ho visto link_to (: back) e ho pensato che: back potrebbe funzionare in redirect_to (: back), ma non è un caso.

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

Qualche idea su come potrei farlo funzionare. Sembra un problema che potrebbe essere facilmente risolto, ma sono nuovo di RoR.

Risposte:


323

Nella tua azione di modifica, archivia l'URL richiedente nell'hash della sessione, disponibile tra più richieste:

session[:return_to] ||= request.referer

Quindi reindirizza ad esso nell'azione di aggiornamento, dopo un salvataggio riuscito:

redirect_to session.delete(:return_to)

68
Suggerirei redirect_to session.delete(:return_to)nell'azione di aggiornamento. Questo pulisce il valore dalla sessione, poiché non è più necessario.
stigi,

19
avere diverse schede aperte confonde questa logica?
jones

12
Non potresti proprio redirect_to request.referer?
Elle Mundy,

1
@DanMundy No, per funzionare dovrebbe essere request.referer.referer, se ciò fosse possibile. @Jaime Bellmyer Perché ||=?
x-yuri,

@jones si. C'è anche confusione se si passa a un'altra modifica del modello. Sono anche interessato al perché || =
Mauro,

99

Perché redirect_to(:back)non funziona per te, perché è un non andare?

redirect_to(:back)funziona come un incanto per me. È solo una scorciatoia per redirect_to(request.env['HTTP_REFERER'])

http://apidock.com/rails/ActionController/Base/redirect_to (pre Rails 3) o http://apidock.com/rails/ActionController/Redirecting/redirect_to (Rails 3)

Si noti che redirect_to(:back)è deprecato in Rails 5. È possibile utilizzare

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


12
redirect_to :backnon funziona bene neanche per me, diciamo che visiti /posts/new, questo è impostato come referente per la richiesta successiva, quindi dopo che il modulo è stato inviato correttamente mostra di nuovo il modulo, ad es /posts/new. Funziona comunque bene per altri scopi.
Kris,

Cioè, OP vuole reindirizzare due volte indietro. Scommetto che poteva solo redirect_to projects_path.
x-yuri,

Si. redirect_back non funziona altrettanto bene in Rails 5
strizzwald il

@strizzwald cosa significa "non funziona bene"? Qualche dettaglio?
Pascal,

@pascalbetz, Quello che intendevo dire è che se HTTP_REFERERnon impostato, potresti ottenere ActionController::RedirectBackError, in quel caso dovresti salvare da questa eccezione. Da quanto ho capito, l'utilizzo redirect_backnon richiede alcuna gestione delle eccezioni poiché sei obbligato a fornire fallback_location. Forse 'non funziona bene' non è il modo giusto per dirlo.
Strizzwald,

45

Mi piace il metodo di Jaime con un'eccezione, ha funzionato meglio per me ri-memorizzare il referer ogni volta:

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

Il motivo è che se modifichi più oggetti, verrai sempre reindirizzato al primo URL che hai archiviato nella sessione con il metodo Jaime. Ad esempio, supponiamo che io abbia oggetti Apple e Orange. Modifica Apple e session[:return_to]viene impostato sul referer di quell'azione. Quando vado a modificare le arance usando lo stesso codice, session[:return_to]non mi imposterò perché è già definito. Quindi, quando aggiorno Orange, verrò inviato al referer della precedente azione di modifica di Apple #.


sì, ma puoi suggerire cosa fare se accidentalmente lo stesso URL è stato memorizzato come sei? Sei alla mela e vieni dalla mela. E vuoi la posizione precedente
Uko,

33

Ecco come lo facciamo nella nostra applicazione

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

In questo modo memorizzi solo l'ultima richiesta GET nel :return_toparametro di sessione, quindi tutti i moduli, anche quando POST con più tempi funzionerebbe :return_to.


3
request.request_urinon è più disponibile, quindi suggerisco di utilizzare request.fullpathinvece
anka il

@anka Aggiornato. Grazie per il commento
MBO

2
sì, è abbastanza buono. Vorrei solo suggerire di non usare generalmente ande ornelle ifdichiarazioni. Usa &&e ||invece. Dettagli qui .
Achille,

19

In Rails 5, secondo le istruzioni in Rails Guides, puoi utilizzare:

redirect_back(fallback_location: root_path)

La posizione 'back' viene estratta dall'intestazione HTTP_REFERER che non è garantita per essere impostata dal browser. Ecco perché dovresti fornire un 'fallback_location'.


Questa funzione appare nelle rotaie 5.
Chambeur

@pSkarl Come posso passare un noticeoggetto con l' redirect_backistruzione per dire all'utente che qualcosa è andato storto con un messaggio flash?
alexventuraio,

2
Beh, ho potuto risolvere questo facendo: redirect_back(fallback_location: root_path, notice: "Something went wrong!"). Spero che possa aiutare in qualche modo.
alexventuraio,

18

request.referer è impostato da Rack ed è impostato come segue:

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

Basta fare un redirect_to request.referere reindirizzerà sempre alla vera pagina di riferimento, o root_path ('/'). Questo è essenziale quando si superano i test che falliscono in caso di direct-nav su una determinata pagina in cui il controller lancia un redirect_to: back


Non sono sicuro di quale file stavi guardando ma alla fonte del rack, ecco come è refererstato definito a partire dal 28 marzo 2011 , ed è così come è stato definito oggi . Cioè, || '/'non fa parte della definizione.
maček,

1

Per coloro che sono interessati, ecco la mia implementazione che estende la risposta originale di MBO (scritta contro le rotaie 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.