¿Cómo redirigir a la página anterior en Ruby On Rails?


186

Tengo una página que enumera todos los proyectos que tienen encabezados y paginación ordenables.

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

Elijo editar uno de los proyectos

path:
projects/436/edit

Cuando hago clic en guardar en esa página, llama al controlador de proyectos / método de actualización. Después de actualizar el código, quiero redirigir a la ruta en la que estaba antes de hacer clic en editar un proyecto específico. En otras palabras, quiero estar en la misma página con la misma clasificación.

Vi link_to (: back) y pensé que: back podría funcionar en redirect_to (: back), pero eso no es posible.

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

Alguna idea sobre cómo podría hacer que esto funcione. Parece un problema que se resolvería fácilmente, pero soy nuevo en RoR.

Respuestas:


323

En su acción de edición, almacene la url solicitante en el hash de sesión, que está disponible en varias solicitudes:

session[:return_to] ||= request.referer

Luego, redirígelo en tu acción de actualización, después de un guardado exitoso:

redirect_to session.delete(:return_to)

68
Sugeriría redirect_to session.delete(:return_to)en la acción de actualización. Esto limpia el valor de la sesión, ya que ya no es necesario.
— stigi

19
¿No tiene varias pestañas abiertas confundir esta lógica?
— jones

12
¿No podrías simplemente redirect_to request.referer?
— Elle Mundy

1
@DanMundy No, para que funcione debería serlo request.referer.referer, si eso fuera posible. @Jaime Bellmyer ¿Por qué ||=?
— x-yuri

@ Jones sí. También hay confusión si cambia a otra edición de modelo. También estoy interesado en por qué || =
— Mauro

99

¿Por qué redirect_to(:back)no funciona para ti, por qué es un no ir?

redirect_to(:back)Funciona como un encanto para mí. Es solo un atajo para 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)

Tenga en cuenta que redirect_to(:back)está en desuso en Rails 5. Puede usar

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


12
redirect_to :backtampoco funciona bien para mí, digamos que visita /posts/new, esto se establece como el referente para la próxima solicitud, por lo que después de que el formulario se envíe con éxito, muestra el formulario nuevamente, es decir /posts/new. Sin embargo, funciona bien para otros fines.
— Kris

Es decir, OP quiere redirigir de nuevo dos veces. Apuesto a que podría simplemente redirect_to projects_path.
— x-yuri

Si. redirect_back no funciona tan bien en Rails 5
— strizzwald

@strizzwald ¿qué significa "no funciona bien"? Cualquier detalle?
— Pascal

@pascalbetz, lo que quise decir es que si HTTP_REFERERno está configurado, es posible ActionController::RedirectBackErrorque tenga que rescatarlo de esta excepción en ese caso. Según tengo entendido, el uso redirect_backno requiere ningún manejo de excepciones, ya que está obligado a proporcionar fallback_location. Tal vez "no funciona bien" no es la forma correcta de decirlo.
— Strizzwald

45

Me gusta el método de Jaime con una excepción, funcionó mejor para mí volver a almacenar el árbitro cada vez:

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

La razón es que si edita varios objetos, siempre será redirigido a la primera URL que almacenó en la sesión con el método de Jaime. Por ejemplo, digamos que tengo objetos Apple y Orange. Edito Apple y me pongo session[:return_to]al árbitro de esa acción. Cuando vaya a editar Naranjas con el mismo código, session[:return_to]no se configurará porque ya está definido. Entonces, cuando actualice el Orange, me enviarán al árbitro de la acción de edición Apple # anterior.


sí, pero ¿puede sugerir qué hacer si accidentalmente se almacenó la misma URL que usted? Estás en Apple y vienes de Apple. Y quieres ubicación anterior
— Uko

33

Así es como lo hacemos en nuestra aplicación

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 esta manera, solo almacena la última solicitud GET en el :return_toparámetro de sesión, por lo que todos los formularios, incluso cuando la POSTed en varias ocasiones funcionaría :return_to.


3
request.request_uriya no está disponible, así que sugiero usar request.fullpathen su lugar
— anka

@anka Actualizado. Gracias por tu comentario
— MBO

2
Sí, eso es bastante bueno. Por lo general, solo sugeriría no usar andy oren las ifdeclaraciones. Uso &&y en su ||lugar. Detalles aquí .
— Achilles

19

En los rieles 5, según las instrucciones de las Guías de rieles, puede usar:

redirect_back(fallback_location: root_path)

La ubicación 'atrás' se extrae del encabezado HTTP_REFERER que no se garantiza que el navegador establezca. Es por eso que debe proporcionar una 'ubicación de retorno'.


Esta característica aparece en los rieles 5.
— Chambeur

@pSkarl ¿Cómo puedo pasar un noticeobjeto con la redirect_backdeclaración para decirle al usuario que algo salió mal con un mensaje flash?
— alexventuraio

2
Bueno, yo podría resolver este haciendo: redirect_back(fallback_location: root_path, notice: "Something went wrong!"). Espero que pueda ayudar de alguna manera.
— alexventuraio

18

request.referer Rack lo establece y se establece de la siguiente manera:

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

Simplemente haga un redirect_to request.referery siempre redirigirá a la página de referencia verdadera, o al root_path ('/'). Esto es esencial cuando se pasan pruebas que fallan en casos de navegación directa a una página en particular en la cual el controlador lanza un redirect_to: back


No estoy seguro de qué archivo estaba mirando, pero en la fuente del rack, así es como refererse definió a partir del 28 de marzo de 2011 , y así es como se define a partir de hoy . Es decir, || '/'no es parte de la definición.
— maček

1

Para aquellos que estén interesados, aquí está mi implementación que amplía la respuesta original de MBO (escrita contra 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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.