Poprawne wykonanie redirect_to: z powrotem w Ruby on Rails, gdy strona odsyłająca nie jest dostępna

91

Mam problem z redirect_to :back. Tak, to odsyłacze.

Często mam wyjątek

(ActionController :: RedirectBackError) "Żądanie HTTP_REFERER nie zostało ustawione w żądaniu do tej akcji, więc nie można pomyślnie wywołać redirect_to: back. Jeśli to jest test, upewnij się, że określono request.env [\" HTTP_REFERER \ "]."

Zdaję sobie sprawę, że jest to spowodowane niedostępnością odsyłacza. Czy istnieje sposób, na przykład, aby ustawić zmienną sesji przy każdym dostępie do ostatnio odwiedzonej strony, a gdy HTTP_REFERER nie jest dostępny, użyć tej zmiennej sesji do przekierowania?

user67050
źródło
Mam ten sam błąd w akcji aktualizacji, co jest dziwne, ponieważ strona odsyłająca nie może być pusta (jak żądanie byłoby z formularza), ale jakiemuś użytkownikowi udało się to zrobić, czego nie wiem jak.
lulalala

Odpowiedzi:

144

Jest mało prawdopodobne, aby zrobić mieć sesję i nie ma odnośnika zwrotnego.

Sytuacja, w której strona odsyłająca nie jest ustawiona, nie jest rzadkością i zwykle ratuję to oczekiwanie:

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

Jeśli robisz to często (co moim zdaniem jest złym pomysłem), możesz zastosować inną metodę, jak sugeruje Maran.

BTW Myślę, że to zły pomysł, ponieważ powoduje to niejednoznaczność przepływu użytkowników. Tylko w przypadku logowania jest to sensowne.

AKTUALIZACJA : Jak kilka osób zauważyło, to już nie działa z Railsami 5. Zamiast tego użyj redirect_back, ta metoda obsługuje również rezerwę. Kod staje się wtedy:

def some_method
  redirect_back fallback_location: root_path
end
zaszkodzić
źródło
4
Podejrzewam, że zmieniłbym to, aby zamiast tego użyć rescue_from.
Bob Aman
1
@BobAman IMO moglibyśmy użyć, rescue_fromgdyby kontroler miał wieleredirect_to :back
Theo B
nie działa z railsami 5, ActionController :: RedirectBackError jest niezdefiniowany ... jakie rozwiązanie?
Matrix
Użyj tego zamiast:redirect_to (request.referrer || root_url)
Abhi
38

Oto moja mała metoda 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

Możesz przekazać opcjonalny adres URL, aby przejść w inne miejsce, jeśli http_refferrer jest puste.

Mirko
źródło
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

Spróbuj tego! (Dzięki wtyczce Authlogic )

Maran
źródło
22
To dobre rozwiązanie, ale zachęcam każdego, kto go używa, aby pamiętał, że może on „zepsuć się” w sposób bardzo mylący dla użytkownika, jeśli korzysta z wielu kart do przeglądania Twojej aplikacji.
Mitch Lindgren,
3
+1 Za udzielenie odpowiedzi na pytanie i nie krytykowanie metod projektowania.
Abe Petrillo
31

Podstawowa funkcja

redirect_backjest podstawową funkcją Rails 5+, jest dostępna w ActionController::Redirectingmodule, który jest już zawarty w ApplicationController::Base.

OSTRZEŻENIE O DEPRECATION: redirect_to :backjest przestarzałe i zostanie usunięte z Rails 5.1. Użyj redirect_back(fallback_location: fallback_location)gdzie fallback_locationoznacza lokalizację do użycia, jeśli żądanie nie zawiera informacji o odnośniku HTTP.

EDYCJA: źródło

Cyril Duchon-Doris
źródło
Link do źródła, proszę
Chris Bloom
1
@ Chrisbloom7 To jest ostrzeżenie, które otrzymałem podczas uruchamiania Rails 5.0.0beta3 z redirect_to :back.
Cyril Duchon-Doris
21

Może jest już późno, ale chciałbym podzielić się moją metodą, która również zachowuje opcje:

  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

Możesz go używać tak jak:

redirect_back_or_default(some_path, :notice => 'Hello from redirect', :status => 301)
troex
źródło
14

aktualizacja: Rails 5 dodał metodę redirect_back ( https://github.com/rails/rails/pull/22506/ ), lepiej po prostu użyj:

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

W przypadku szyn niższych niż 5.0 można nadal używać starego sposobu poniżej:

podobnie jak odpowiedź @ troex, dodaj to do kontrolera aplikacji

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

następnie użyj go w kontrolerze

redirect_back_or_default answer_path(answer), flash: { error: I18n.t('m.errors')}
longkt90
źródło
0

Niedawno napotkałem ten sam problem, w którym musiałem przekierować :backlub przejść do określonej strony. Po przejściu do wielu rozwiązań w końcu znalazłem to, co jest proste i wydaje się, że rozwiązuje problem:


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

Jeśli chcesz użyć sessionszczegółów, zrób to w dalszej części kodu.

Rahul Goyal
źródło