Chciałbym „sfałszować” stronę 404 w Railsach. W PHP po prostu wysyłam nagłówek z kodem błędu jako takim:
header("HTTP/1.0 404 Not Found");
Jak to się robi z Railsami?
źródło
Chciałbym „sfałszować” stronę 404 w Railsach. W PHP po prostu wysyłam nagłówek z kodem błędu jako takim:
header("HTTP/1.0 404 Not Found");
Jak to się robi z Railsami?
Nie renderuj 404 samemu, nie ma powodu; Railsy mają już tę funkcję wbudowaną. Jeśli chcesz wyświetlić stronę 404, utwórz render_404
metodę (lub not_found
jak ją nazwałem) w ApplicationController
następujący sposób:
def not_found
raise ActionController::RoutingError.new('Not Found')
end
Poręcze również obsługują AbstractController::ActionNotFound
iActiveRecord::RecordNotFound
ten sam sposób.
To robi dwie rzeczy lepiej:
1) Używa wbudowanego rescue_from
modułu obsługi Railsów do renderowania strony 404, i 2) przerywa wykonywanie kodu, pozwalając ci robić fajne rzeczy, takie jak:
user = User.find_by_email(params[:email]) or not_found
user.do_something!
bez konieczności pisania brzydkich instrukcji warunkowych.
Jako bonus, jest również bardzo łatwy w obsłudze w testach. Na przykład w teście integracji rspec:
# RSpec 1
lambda {
visit '/something/you/want/to/404'
}.should raise_error(ActionController::RoutingError)
# RSpec 2+
expect {
get '/something/you/want/to/404'
}.to raise_error(ActionController::RoutingError)
I najmniejszy:
assert_raises(ActionController::RoutingError) do
get '/something/you/want/to/404'
end
LUB odnieś więcej informacji z Railsów, render 404 nie znaleziono z działania kontrolera
ActionController::RecordNotFound
jest lepsza opcja?expect { visit '/something/you/want/to/404' }.to raise_error(ActionController::RoutingError)
/ via stackoverflow.com/a/1722839/993890Status HTTP 404
Aby zwrócić nagłówek 404, po prostu użyj
:status
opcji metody renderowania.Jeśli chcesz wyrenderować standardową stronę 404, możesz wyodrębnić funkcję w metodzie.
i nazwij to w swoim działaniu
Jeśli chcesz, aby akcja wyświetlała stronę błędu i zatrzymywała się, po prostu użyj instrukcji return.
ActiveRecord i HTTP 404
Pamiętaj również, że Railsy ratują niektóre błędy ActiveRecord, takie jak
ActiveRecord::RecordNotFound
wyświetlanie strony błędu 404.Oznacza to, że nie musisz samodzielnie ratować tej akcji
User.find
podnosi,ActiveRecord::RecordNotFound
gdy użytkownik nie istnieje. To bardzo potężna funkcja. Spójrz na następujący kodMożesz to uprościć, delegując czek do Rails. Po prostu użyj wersji Bang.
źródło
Nowo wybrana odpowiedź przesłana przez Stevena Sorokę jest bliska, ale niepełna. Sam test ukrywa fakt, że nie zwraca prawdziwego 404 - zwraca status 200 - „sukces”. Oryginalna odpowiedź była bliższa, ale próbowała renderować układ tak, jakby nie wystąpiła awaria. To naprawia wszystko:
Oto typowy mój zestaw testowy dla czegoś, co spodziewam się zwrócić 404, przy użyciu dopasowań RSpec i Shoulda:
Ta zdrowa paranoja pozwoliła mi dostrzec niedopasowanie typu zawartości, gdy wszystko inne wyglądało brzoskwiniowo :) Sprawdzam wszystkie te elementy: przypisane zmienne, kod odpowiedzi, typ treści odpowiedzi, renderowany szablon, renderowany układ, wiadomości flash.
Pominę sprawdzanie typu zawartości w aplikacjach, które są ściśle HTML ... czasami. W końcu „sceptyk sprawdza WSZYSTKIE szuflady” :)
http://dilbert.com/strips/comic/1998-01-20/
FYI: Nie polecam testowania rzeczy, które dzieją się w kontrolerze, tj. „Powinien_jasować”. To, na czym Ci zależy, to wynik. Moje powyższe testy pozwoliły mi wypróbować różne rozwiązania, a testy pozostają takie same, niezależnie od tego, czy rozwiązanie generuje wyjątek, specjalne renderowanie itp.
źródło
render :text => 'Not Found', :status => :not_found
.config.consider_all_requests_local
ustawiony parametr true w swoimenvironments/development.rb
pliku. Jeśli zgłaszasz błąd, jak opisano w przyjętym rozwiązaniu, w inscenizacji / produkcji, na pewno dostaniesz 404, a nie 200.Możesz także użyć pliku renderowania:
Gdzie możesz użyć układu, czy nie.
Inną opcją jest użycie wyjątków, aby to kontrolować:
źródło
Wybrana odpowiedź nie działa w Rails 3.1+, ponieważ program obsługi błędów został przeniesiony do oprogramowania pośredniego (patrz problem z github ).
Oto rozwiązanie, z którego jestem zadowolony.
W
ApplicationController
:oraz w
application.rb
:I w moich zasobach (pokaż, edytuj, aktualizuj, usuń):
Można to z pewnością poprawić, ale przynajmniej mam inne widoki dla not_found i internal_error bez nadpisywania podstawowych funkcji Railsów.
źródło
|| not_found
części, po prostu zadzwońfind!
(zauważ huk), a wyrzuci ActiveRecord :: RecordNotFound, gdy nie będzie można odzyskać zasobu. Dodaj również ActiveRecord :: RecordNotFound do tablicy w warunku if.StandardError
i nie naException
wszelki wypadek. Właściwie zostawię standardową stronę statyczną 500 i w ogóle nierender_500
rescue_from
te pomogą ci ...
Kontroler aplikacji
Kontroler błędów
views / error / error_404.html.haml
źródło
po prostu dodaj to do strony, którą chcesz wyrenderować na stronie błędu 404 i gotowe.
źródło
Chciałem rzucić „normalny” 404 dla każdego zalogowanego użytkownika, który nie jest administratorem, więc ostatecznie napisałem coś takiego w Rails 5:
źródło
źródło
Aby przetestować obsługę błędów, możesz zrobić coś takiego:
źródło
Jeśli chcesz obsługiwać różne 404 na różne sposoby, rozważ złapanie ich w kontrolerach. Umożliwi to wykonywanie czynności takich jak śledzenie liczby 404 wygenerowanych przez różne grupy użytkowników, wsparcie w interakcji z użytkownikami, aby dowiedzieć się, co poszło nie tak / jaka część doświadczenia użytkownika może wymagać ulepszenia, testowania A / B itp.
Umieściłem tutaj podstawową logikę w ApplicationController, ale można ją również umieścić w bardziej szczegółowych kontrolerach, aby mieć specjalną logikę tylko dla jednego kontrolera.
Powodem, dla którego używam if z ENV [„RESCUE_404”], jest to, że mogę przetestować podnoszenie AR :: RecordNotFound w izolacji. W testach mogę ustawić ten ENV var na false, a mój rescue_from nie będzie strzelał. W ten sposób mogę przetestować podniesienie niezależnie od logiki warunkowej 404.
źródło