Faire correctement redirect_to: retour dans Ruby on Rails lorsque le référent n'est pas disponible

91

J'ai un problème avec redirect_to :back. Oui, ce sont des référents.

Je reçois souvent l'exception

(ActionController :: RedirectBackError) "Aucun HTTP_REFERER n'a été défini dans la requête pour cette action, donc redirect_to: back n'a pas pu être appelé avec succès. S'il s'agit d'un test, assurez-vous de spécifier request.env [\" HTTP_REFERER \ "]."

Je me rends compte que c'est le résultat d'un référent qui n'est pas disponible. Existe-t-il un moyen, par exemple, de définir une variable de session à chaque accès avec la dernière page visitée et, lorsque HTTP_REFERER n'est pas disponible, d'utiliser cette variable de session pour la redirection?

user67050
la source
J'ai la même erreur dans une action de mise à jour, ce qui est étrange car le référent ne peut pas être vide (car la demande proviendrait d'un formulaire), mais un utilisateur a simplement réussi à le faire, ce que je ne sais pas comment.
lulalala

Réponses:

144

Il est peu probable que vous faire une séance et ne pas avoir un referrer.

La situation dans laquelle un référent n'est pas défini n'est pas si rare et je sauve généralement cette attente:

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

Si vous faites cela souvent (ce que je pense être une mauvaise idée), vous pouvez l'envelopper dans une autre méthode comme le suggère Maran.

BTW Je pense que c'est une mauvaise idée car cela rend le flux utilisateur ambigu. Ce n'est que dans le cas d'une connexion que cela est raisonnable.

MISE À JOUR : Comme plusieurs personnes l'ont souligné, cela ne fonctionne plus avec Rails 5. Au lieu de cela, utilisez redirect_back, cette méthode prend également en charge une solution de secours. Le code devient alors:

def some_method
  redirect_back fallback_location: root_path
end
nuire
la source
4
Je soupçonne que je modifierais cela pour utiliser à la place rescue_from.
Bob Aman
1
@BobAman IMO que nous pourrions utiliser rescue_fromsi le contrôleur avait plusieursredirect_to :back
Theo B
ne fonctionne pas avec les rails 5, ActionController :: RedirectBackError n'est pas défini ... quelle solution?
Matrix
Utilisez ceci à la place:redirect_to (request.referrer || root_url)
Abhi
38

Voici ma petite méthode 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

Vous pouvez passer une URL facultative pour aller ailleurs si http_refferrer est vide.

Mirko
la source
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

Essayez ça! (Merci au plugin Authlogic )

Maran
la source
22
C'est une bonne solution, mais j'exhorte toute personne qui l'utilise à garder à l'esprit qu'elle peut «casser» d'une manière extrêmement déroutante pour l'utilisateur s'il utilise plusieurs onglets pour parcourir votre application.
Mitch Lindgren
3
+1 Pour répondre à la question et ne pas critiquer les méthodes de conception.
Abe Petrillo
31

Fonctionnalité principale

redirect_backest une fonctionnalité principale de Rails 5+, elle est disponible dans le ActionController::Redirectingmodule qui est déjà inclus dans ApplicationController::Base.

AVERTISSEMENT DE DÉPRÉCIATION: redirect_to :backest obsolète et sera supprimé de Rails 5.1. Veuillez utiliser redirect_back(fallback_location: fallback_location)where fallback_locationreprésente l'emplacement à utiliser si la requête ne contient aucune information de référent HTTP.

EDIT: source

Cyril Duchon-Doris
la source
Lien vers la source, s'il vous plaît
Chris Bloom
1
@ Chrisbloom7 C'est un message d'avertissement que j'ai eu lors de l'exécution de Rails 5.0.0beta3 avec redirect_to :back.
Cyril Duchon-Doris
21

Il est peut-être tard mais j'aimerais partager ma méthode qui préserve également les options:

  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

Vous pouvez l'utiliser comme:

redirect_back_or_default(some_path, :notice => 'Hello from redirect', :status => 301)
troex
la source
14

mise à jour: Rails 5 a ajouté la méthode redirect_back ( https://github.com/rails/rails/pull/22506/ ), mieux vaut simplement utiliser:

redirect_back fallback_location: answer_path(answer), flash: { error: I18n.t('m.errors')}

Pour les rails inférieurs à 5.0, vous pouvez toujours utiliser l'ancienne méthode ci-dessous:

similaire à la réponse de @ troex, ajoutez ceci à votre contrôleur d'application

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

puis utilisez-le dans votre manette

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

Récemment, j'ai rencontré le même problème où je devais rediriger :backou vers une page spécifique. Après être allé à beaucoup de solution, j'ai finalement trouvé celle-ci qui est simple et semble résoudre le problème:


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

Si vous souhaitez utiliser les sessiondétails, faites-le dans la partie autre du code.

Rahul Goyal
la source