J'ai une page qui répertorie tous les projets avec des en-têtes triables et une pagination.
path:
/projects?order=asc&page=3&sort=code
Je choisis d'éditer l'un des projets
path:
projects/436/edit
Lorsque je clique sur Enregistrer sur cette page, il appelle la méthode contrôleur de projets/mise à jour. Après avoir mis à jour le code, je souhaite rediriger le chemin sur lequel je me trouvais avant de cliquer sur Modifier un projet spécifique. En d'autres termes, je veux être sur la même page avec le même tri.
J'ai vu link_to (: back) et j'ai pensé que: back pouvait fonctionner dans redirect_to (: back), mais ce n'est pas possible.
puts YAML::dump(:back)
yields the following:
:back
Des idées sur comment je pourrais obtenir que cela fonctionne. Cela semble être un problème qui pourrait être facilement résolu, mais je suis nouveau sur RoR.
Dans votre action d'édition, stockez l'URL demandée dans le hachage de session, disponible pour plusieurs demandes:
session[:return_to] ||= request.referer
Puis redirigez-le dans votre action de mise à jour, après une sauvegarde réussie:
redirect_to session.delete(:return_to)
Pourquoi redirect_to(:back)
ne fonctionne-t-il pas pour vous, pourquoi ne pas y aller?
redirect_to(:back)
fonctionne comme un charme pour moi. C'est juste un raccourci pour redirect_to(request.env['HTTP_REFERER'])
http://apidock.com/Rails/ActionController/Base/redirect_to (pre Rails 3) ou http://apidock.com/Rails/ActionController/ Redirection/redirect_to (Rails 3)
Veuillez noter que redirect_to(:back)
est obsolète dans Rails 5. Vous pouvez utiliser
redirect_back(fallback_location: 'something')
à la place (voir http://blog.bigbinary.com/2016/02/29/Rails-5-improves-redirect_to_back-with-redirect-back.html )
J'aime la méthode de Jaime à une exception près, cela a mieux fonctionné pour moi de ré-enregistrer le référant à chaque fois:
def edit
session[:return_to] = request.referer
...
La raison en est que si vous modifiez plusieurs objets, vous serez toujours redirigé vers la première URL que vous avez enregistrée dans la session avec la méthode de Jaime. Par exemple, supposons que j’ai les objets Apple et Orange. J'édite Apple et session[:return_to]
est défini sur le référent de cette action. Quand je vais éditer des oranges en utilisant le même code, session[:return_to]
ne sera pas défini car il est déjà défini. Ainsi, lorsque je mettrai à jour Orange, je serai envoyé au référent de la précédente action Apple # edit.
Voici comment nous le faisons dans notre application
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
De cette façon, vous ne stockez que la dernière requête GET dans le paramètre de session :return_to
, de sorte que tous les formulaires, même lorsque POSTed a plusieurs heures, fonctionnent avec :return_to
.
request.referer
est défini par le rack et se présente comme suit:
def referer
@env['HTTP_REFERER'] || '/'
end
Faites juste un redirect_to request.referer
et il sera toujours redirigé vers la vraie page de référence, ou le chemin_racine ('/'). Ceci est essentiel lorsque les tests échouent en cas de navigation directe vers une page particulière dans laquelle le contrôleur envoie une redirection_to: retour
Dans Rails 5, conformément aux instructions de Rails Guides, vous pouvez utiliser:
redirect_back(fallback_location: root_path)
L'emplacement 'back' est tiré de l'en-tête HTTP_REFERER, qui n'est pas nécessairement défini par le navigateur. C'est pourquoi vous devriez fournir un 'emplacement de repli'.
Pour ceux qui sont intéressés, voici mon implémentation qui étend la réponse originale de MBO (écrite contre 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