Я хотел бы «подделать» страницу 404 в Rails. В PHP я бы просто отправил заголовок с кодом ошибки как таковой:
header("HTTP/1.0 404 Not Found");
Как это сделать с Rails?
источник
Я хотел бы «подделать» страницу 404 в Rails. В PHP я бы просто отправил заголовок с кодом ошибки как таковой:
header("HTTP/1.0 404 Not Found");
Как это сделать с Rails?
Не визуализируйте 404 самостоятельно, нет причин для этого; В Rails эта функциональность уже встроена. Если вы хотите показать страницу 404, создайте render_404
метод (или not_found
как я его назвал) ApplicationController
следующим образом:
def not_found
raise ActionController::RoutingError.new('Not Found')
end
Rails тоже обрабатывает AbstractController::ActionNotFound
, и так ActiveRecord::RecordNotFound
же.
Это делает две вещи лучше:
1) Он использует встроенный rescue_from
обработчик Rails для рендеринга страницы 404, и 2) он прерывает выполнение вашего кода, позволяя вам делать такие приятные вещи, как:
user = User.find_by_email(params[:email]) or not_found
user.do_something!
без необходимости писать некрасивые условные высказывания.
В качестве бонуса, это также очень легко обрабатывать в тестах. Например, в тесте интеграции 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)
И минитест:
assert_raises(ActionController::RoutingError) do
get '/something/you/want/to/404'
end
ИЛИ см. Дополнительную информацию из рендера Rails 404, не найденного в действии контроллера
ActionController::RecordNotFound
это лучший вариант?expect { visit '/something/you/want/to/404' }.to raise_error(ActionController::RoutingError)
/ via stackoverflow.com/a/1722839/993890HTTP 404 Статус
Чтобы вернуть заголовок 404, просто используйте
:status
опцию для метода рендеринга.Если вы хотите отобразить стандартную страницу 404, вы можете извлечь функцию в методе.
и назовите это в вашем действии
Если вы хотите, чтобы действие отобразило страницу с ошибкой и остановилось, просто используйте оператор return.
ActiveRecord и HTTP 404
Также помните, что Rails спасает некоторые ошибки ActiveRecord, такие как
ActiveRecord::RecordNotFound
отображение страницы с ошибкой 404.Это означает, что вам не нужно спасать это действие самостоятельно
User.find
вызывает,ActiveRecord::RecordNotFound
когда пользователь не существует. Это очень мощная функция. Посмотрите на следующий кодВы можете упростить это, делегировав Rails проверку. Просто используйте версию взрыва.
источник
Недавно выбранный ответ, представленный Стивеном Сорокой, близок, но не завершен. Сам тест скрывает тот факт, что это не возвращает истинный 404 - он возвращает статус 200 - «успех». Первоначальный ответ был ближе, но попытался отобразить макет, как если бы не произошло никакого сбоя. Это исправляет все:
Вот типичный мой тестовый набор для чего-то, что я ожидаю вернуть 404, используя сопоставители RSpec и Shoulda:
Эта здоровая паранойя позволила мне обнаружить несоответствие типов контента, когда все остальное выглядело замечательно :) Я проверяю все эти элементы: назначенные переменные, код ответа, тип контента ответа, представленный шаблон, отображаемый макет, флэш-сообщения.
Я пропущу проверку типа контента в приложениях, которые строго HTML ... иногда. Ведь «скептик проверяет ВСЕ ящики» :)
http://dilbert.com/strips/comic/1998-01-20/
К вашему сведению: я не рекомендую проверять то, что происходит в контроллере, то есть «should_raise». Что вас волнует, так это результат. Мои тесты, приведенные выше, позволили мне попробовать различные решения, и тесты остаются прежними, независимо от того, вызывает ли решение исключение, специальный рендеринг и т. Д.
источник
render :text => 'Not Found', :status => :not_found
.config.consider_all_requests_local
параметр true в вашемenvironments/development.rb
файле. Если вы поднимете ошибку, как описано в принятом решении, в постановке / производстве, вы обязательно получите 404, а не 200.Вы также можете использовать файл рендеринга:
Где вы можете использовать макет или нет.
Другой вариант - использовать исключения для управления им:
источник
Выбранный ответ не работает в Rails 3.1+, так как обработчик ошибок был перемещен в промежуточное ПО (см. Проблему с github ).
Вот решение, которое я нашел, которым я очень доволен.
В
ApplicationController
:и в
application.rb
:И в моих ресурсах (показать, отредактировать, обновить, удалить):
Это, безусловно, можно улучшить, но, по крайней мере, у меня есть разные представления для not_found и internal_error без переопределения основных функций Rails.
источник
|| not_found
часть, просто вызовитеfind!
(заметьте взрыв), и он выдаст ActiveRecord :: RecordNotFound, когда ресурс не может быть получен. Также добавьте ActiveRecord :: RecordNotFound в массив в условии if.StandardError
и неException
, на всякий случай. На самом деле я оставлю стандартную 500 статическую страницу и не буду использовать пользовательскуюrender_500
вообще, то есть я буду явноrescue_from
массив ошибок, связанных с 404это поможет вам ...
Контроллер приложений
Контроллер ошибок
просмотров / ошибки / error_404.html.haml
источник
просто добавьте это на страницу, которую вы хотите отобразить на странице ошибки 404, и все готово.
источник
Я хотел выдать «нормальный» 404 для любого вошедшего в систему пользователя, который не является администратором, поэтому я написал что-то подобное в Rails 5:
источник
источник
Чтобы проверить обработку ошибок, вы можете сделать что-то вроде этого:
источник
Если вы хотите обрабатывать разные 404 по-разному, подумайте о том, чтобы перехватить их в своих контроллерах. Это позволит вам выполнять такие действия, как отслеживание числа 404, сгенерированного различными группами пользователей, поддержка взаимодействия с пользователями, чтобы выяснить, что пошло не так / какая часть пользовательского опыта может потребоваться настроить, выполнить A / B-тестирование и т. Д.
Здесь я поместил базовую логику в ApplicationController, но ее также можно поместить в более конкретные контроллеры, чтобы иметь специальную логику только для одного контроллера.
Причина, по которой я использую if с ENV ['RESCUE_404'], заключается в том, что я могу проверить поднятие AR :: RecordNotFound изолированно. В тестах я могу установить для этого ENV var значение false, и мой rescue_from не сработает. Таким образом, я могу проверить повышение отдельно от условной логики 404.
источник