Fazendo redirect_to: de volta ao Ruby on Rails corretamente quando o referrer não está disponível

91

Estou tendo um problema com redirect_to :back. Sim, são referenciadores.

Costumo obter a exceção

(ActionController :: RedirectBackError) "Nenhum HTTP_REFERER foi definido na solicitação para esta ação, então redirect_to: back não pôde ser chamado com sucesso. Se este for um teste, certifique-se de especificar request.env [\" HTTP_REFERER \ "]."

Percebo que isso é resultado da indisponibilidade de um referenciador. Existe uma maneira de, por exemplo, definir uma variável de sessão em cada acesso com a última página visitada e, quando HTTP_REFERER não estiver disponível, utilizar esta variável de sessão para redirecionar?

user67050
fonte
Eu tenho o mesmo erro em uma ação de atualização, o que é estranho porque o referrer não poderia estar vazio (como a solicitação seria de um formulário), mas algum usuário conseguiu fazer isso que eu não sei como.
lulalala

Respostas:

144

É improvável que você faz tem uma sessão e não tem um referencial.

A situação em que um referenciador não é definido não é tão incomum e eu geralmente resgato essa expectativa:

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

Se você fizer isso com frequência (o que eu acho uma má ideia), pode envolvê-lo em outro método, como sugere Maran.

BTW, acho que é uma má ideia porque torna o fluxo de usuário ambíguo. Somente no caso de um login isso é sensato.

ATUALIZAÇÃO : Como várias pessoas apontaram, isso não funciona mais com o Rails 5. Em vez disso, use redirect_back, este método também suporta um fallback. O código então se torna:

def some_method
  redirect_back fallback_location: root_path
end
prejuízo
fonte
4
Suspeito que alteraria isso para usar rescue_from.
Bob Aman
1
@BobAman IMO que poderíamos usar rescue_fromse o controlador tivesse váriosredirect_to :back
Theo B
não funciona com rails 5, ActionController :: RedirectBackError é indefinido ... qual solução?
Matrix
Em vez disso, use:redirect_to (request.referrer || root_url)
Abhi
38

Aqui está meu pequeno 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

Você pode passar um url opcional para ir para outro lugar se http_refferrer estiver em branco.

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

Tente isso! (Graças ao plugin Authlogic )

Maran
fonte
22
Esta é uma boa solução, mas recomendo que qualquer pessoa que a use tenha em mente que ela pode "quebrar" de uma maneira extremamente confusa para o usuário se ele estiver usando várias guias para navegar em seu aplicativo.
Mitch Lindgren
3
+1 Para responder à pergunta e não criticar os métodos de design.
Abe Petrillo
31

Recurso central

redirect_backé um recurso central do Rails 5+, está disponível no ActionController::Redirectingmódulo que já está incluído no ApplicationController::Base.

AVISO DE DEPRECAÇÃO: redirect_to :backestá obsoleto e será removido do Rails 5.1. Use redirect_back(fallback_location: fallback_location)where fallback_locationrepresenta o local a ser usado se a solicitação não tiver informações de referenciador HTTP.

EDIT: fonte

Cyril Duchon-Doris
fonte
Link para a fonte, por favor
Chris Bloom
1
@ Chrisbloom7 Esta é uma mensagem de aviso que recebi enquanto rodava o Rails 5.0.0beta3 com redirect_to :back.
Cyril Duchon-Doris
21

Talvez seja tarde, mas gostaria de compartilhar meu método que também preserva as opções:

  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

Você pode usá-lo como:

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

atualizado: Rails 5 adicionou o método redirect_back ( https://github.com/rails/rails/pull/22506/ ), melhor apenas usar:

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

Para trilhos inferiores a 5.0 ainda pode usar a forma antiga abaixo:

semelhante à resposta de @ troex, adicione isso ao seu controlador de aplicativo

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

em seguida, use-o em seu controlador

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

Recentemente, encontrei o mesmo problema em que tive que redirecionar :backou para uma página específica. Depois de buscar muitas soluções, finalmente descobri que é simples e parece resolver o problema:


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

Se você quiser usar sessiondetalhes, faça-o na outra parte do código.

Rahul Goyal
fonte