Haciendo correctamente redirect_to: de vuelta en Ruby on Rails cuando la referencia no está disponible

91

Tengo un problema con redirect_to :back. Sí, son referencias.

A menudo obtengo la excepción

(ActionController :: RedirectBackError) "No se configuró HTTP_REFERER en la solicitud para esta acción, por lo que no se pudo llamar correctamente a redirect_to: back. Si se trata de una prueba, asegúrese de especificar request.env [\" HTTP_REFERER \ "].

Me doy cuenta de que esto se debe a que una referencia no está disponible. ¿Hay alguna forma de que, por ejemplo, se pueda establecer una variable de sesión en cada acceso con la última página visitada y, cuando HTTP_REFERER no esté disponible, utilizar esta variable de sesión para redirigir?

user67050
fuente
Tengo el mismo error en una acción de actualización, lo cual es extraño porque la referencia no puede estar vacía (ya que la solicitud sería de un formulario), pero algunos usuarios simplemente lograron hacer esto, lo cual no sé cómo.
lulalala

Respuestas:

144

Es poco probable que hacer una sesión y no hacer tener una referencia.

La situación en la que un referente no está configurado no es tan infrecuente y generalmente rescato esa expectativa:

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

Si haces esto a menudo (lo cual creo que es una mala idea) puedes envolverlo en otro método como sugiere Maran.

Por cierto, creo que es una mala idea porque hace que el flujo de usuarios sea ambiguo. Solo en el caso de un inicio de sesión, esto es sensato.

ACTUALIZACIÓN : Como varias personas señalaron, esto ya no funciona con Rails 5. En su lugar, utilice redirect_backeste método también admite un respaldo. El código luego se convierte en:

def some_method
  redirect_back fallback_location: root_path
end
daño
fuente
4
Sospecho que alteraría esto para usar rescue_from en su lugar.
Bob Aman
1
@BobAman IMO podríamos usar rescue_fromsi el controlador tuviera múltiplesredirect_to :back
Theo B
no funciona con rieles 5, ActionController :: RedirectBackError no está definido ... ¿qué solución?
Matrix
Use esto en su lugar:redirect_to (request.referrer || root_url)
Abhi
38

Aquí está mi pequeño método 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

Puede pasar una URL opcional para ir a otro lugar si http_refferrer está en blanco.

Mirko
fuente
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

¡Trata eso! (Gracias al complemento Authlogic )

Maran
fuente
22
Esta es una buena solución, pero insto a cualquiera que la use a tener en cuenta que puede "romperse" de una manera extremadamente confusa para el usuario si está usando varias pestañas para navegar por su aplicación.
Mitch Lindgren
3
+1 Por responder la pregunta y no criticar los métodos de diseño.
Abe Petrillo
31

Característica principal

redirect_backes una característica principal de Rails 5+, está disponible en el ActionController::Redirectingmódulo que ya está incluido en ApplicationController::Base.

ADVERTENCIA DE DEPRECATION: redirect_to :backestá obsoleto y se eliminará de Rails 5.1. Por favor useredirect_back(fallback_location: fallback_location) donde fallback_locationrepresenta la ubicación que se utilizará si la solicitud no tiene información de referencia HTTP.

EDITAR: fuente

Cyril Duchon-Doris
fuente
Enlace a la fuente, por favor
Chris Bloom
1
@ Chrisbloom7 Este es un mensaje de advertencia que recibí mientras ejecutaba Rails 5.0.0beta3 con redirect_to :back.
Cyril Duchon-Doris
21

Tal vez sea tarde, pero me gustaría compartir mi método que también conserva las opciones:

  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

Puedes usarlo como:

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

actualizado: Rails 5 agregó el método redirect_back ( https://github.com/rails/rails/pull/22506/ ), mejor solo use:

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

Para rieles inferiores a 5.0 aún se puede usar la forma anterior a continuación:

similar a la respuesta de @ troex, agregue esto a su controlador de aplicación

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

luego úsalo en tu controlador

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

Recientemente, encontré el mismo problema en el que tuve que redirigir :backo a una página específica. Después de buscar muchas soluciones, finalmente encontré esto que es simple y parece resolver el problema:


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

Si desea utilizar los sessiondetalles, hágalo en la parte else del código.

Rahul Goyal
fuente