Me gustaría 'falsificar' una página 404 en Rails. En PHP, simplemente enviaría un encabezado con el código de error como tal:
header("HTTP/1.0 404 Not Found");
¿Cómo se hace eso con Rails?
fuente
Me gustaría 'falsificar' una página 404 en Rails. En PHP, simplemente enviaría un encabezado con el código de error como tal:
header("HTTP/1.0 404 Not Found");
¿Cómo se hace eso con Rails?
No renderice 404 usted mismo, no hay razón para hacerlo; Rails tiene esta funcionalidad incorporada ya. Si desea mostrar una página 404, cree un render_404
método (o not_found
como lo llamé) de ApplicationController
esta manera:
def not_found
raise ActionController::RoutingError.new('Not Found')
end
Los rieles también se manejan AbstractController::ActionNotFound
, y de ActiveRecord::RecordNotFound
la misma manera.
Esto hace dos cosas mejor:
1) Utiliza el rescue_from
controlador integrado de Rails para representar la página 404, y 2) interrumpe la ejecución de su código, permitiéndole hacer cosas agradables como:
user = User.find_by_email(params[:email]) or not_found
user.do_something!
sin tener que escribir declaraciones condicionales feas.
Como beneficio adicional, también es muy fácil de manejar en las pruebas. Por ejemplo, en una prueba de integración 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)
Y minitest:
assert_raises(ActionController::RoutingError) do
get '/something/you/want/to/404'
end
O consulte más información de Rails render 404 no encontrado desde una acción del controlador
ActionController::RecordNotFound
es la mejor opción?expect { visit '/something/you/want/to/404' }.to raise_error(ActionController::RoutingError)
/ via stackoverflow.com/a/1722839/993890HTTP 404 Status
Para devolver un encabezado 404, simplemente use la
:status
opción para el método de representación.Si desea representar la página 404 estándar, puede extraer la característica en un método.
y llámalo en tu acción
Si desea que la acción represente la página de error y se detenga, simplemente use una declaración de devolución.
ActiveRecord y HTTP 404
Recuerde también que Rails rescata algunos errores de ActiveRecord, como
ActiveRecord::RecordNotFound
mostrar la página de error 404.Significa que no necesita rescatar esta acción usted mismo
User.find
plantea unActiveRecord::RecordNotFound
cuando el usuario no existe. Esta es una característica muy poderosa. Mira el siguiente códigoPuede simplificarlo delegando en Rails el cheque. Simplemente use la versión de explosión.
fuente
La respuesta recientemente seleccionada presentada por Steven Soroka es cercana, pero no completa. La prueba en sí misma oculta el hecho de que esto no está devolviendo un verdadero 404, está devolviendo un estado de 200 - "éxito". La respuesta original estaba más cerca, pero intentó renderizar el diseño como si no hubiera ocurrido ninguna falla. Esto arregla todo:
Aquí hay un conjunto de pruebas típico mío para algo que espero devolver 404, usando los emparejadores RSpec y Shoulda:
Esta paranoia saludable me permitió detectar la falta de coincidencia de tipo de contenido cuando todo lo demás parecía color de rosa :) Compruebo todos estos elementos: variables asignadas, código de respuesta, tipo de contenido de respuesta, plantilla renderizada, diseño renderizado, mensajes flash.
Omitiré la verificación del tipo de contenido en aplicaciones que son estrictamente html ... a veces. Después de todo, "un escéptico revisa TODOS los cajones" :)
http://dilbert.com/strips/comic/1998-01-20/
FYI: No recomiendo probar las cosas que están sucediendo en el controlador, es decir, "debería_raise". Lo que te importa es la salida. Mis pruebas anteriores me permitieron probar varias soluciones, y las pruebas siguen siendo las mismas si la solución está generando una excepción, una representación especial, etc.
fuente
render :text => 'Not Found', :status => :not_found
.config.consider_all_requests_local
parámetro establecido en verdadero en tuenvironments/development.rb
archivo. Si genera un error, como se describe en la solución aceptada, en la puesta en escena / producción, definitivamente obtendrá un 404, no un 200.También puede usar el archivo de renderizado:
Donde puede elegir usar el diseño o no.
Otra opción es usar las Excepciones para controlarlo:
fuente
La respuesta seleccionada no funciona en Rails 3.1+ ya que el controlador de errores se movió a un middleware (vea el problema de github ).
Aquí está la solución que encontré con la que estoy bastante contento.
En
ApplicationController
:y en
application.rb
:Y en mis recursos (mostrar, editar, actualizar, eliminar):
Esto ciertamente podría mejorarse, pero al menos, tengo diferentes vistas para not_found e internal_error sin anular las funciones principales de Rails.
fuente
|| not_found
parte, solo llamefind!
(note la explosión) y arrojará ActiveRecord :: RecordNotFound cuando el recurso no se pueda recuperar. Además, agregue ActiveRecord :: RecordNotFound a la matriz en la condición if.StandardError
y noException
, por si acaso. En realidad, dejaré la página estática estándar 500 y norender_500
rescue_from
estos te ayudarán ...
Controlador de aplicaciones
Controlador de errores
vistas / errores / error_404.html.haml
fuente
simplemente agregue esto a la página que desea representar en la página de error 404 y ya está.
fuente
Quería lanzar un 404 'normal' para cualquier usuario conectado que no sea administrador, así que terminé escribiendo algo como esto en Rails 5:
fuente
fuente
Para probar el manejo de errores, puede hacer algo como esto:
fuente
Si desea manejar diferentes 404 de diferentes maneras, considere atraparlos en sus controladores. Esto le permitirá hacer cosas como rastrear la cantidad de 404 generados por diferentes grupos de usuarios, tener soporte para interactuar con los usuarios para averiguar qué salió mal / qué parte de la experiencia del usuario podría necesitar ajustes, hacer pruebas A / B, etc.
He colocado aquí la lógica base en ApplicationController, pero también se puede colocar en controladores más específicos, para tener una lógica especial solo para un controlador.
La razón por la que estoy usando un if con ENV ['RESCUE_404'] es para poder probar el aumento de AR :: RecordNotFound de forma aislada. En las pruebas, puedo establecer esta var ENV en falso, y mi rescate_desde no se disparará. De esta manera puedo probar la subida por separado de la lógica 404 condicional.
fuente