Je voudrais «simuler» une page 404 dans Rails. En PHP, je voudrais simplement envoyer un en-tête avec le code d'erreur en tant que tel:
header("HTTP/1.0 404 Not Found");
Comment cela se fait-il avec Rails?
la source
Je voudrais «simuler» une page 404 dans Rails. En PHP, je voudrais simplement envoyer un en-tête avec le code d'erreur en tant que tel:
header("HTTP/1.0 404 Not Found");
Comment cela se fait-il avec Rails?
Ne restituez pas 404 vous-même, il n'y a aucune raison de le faire; Rails a déjà cette fonctionnalité intégrée. Si vous voulez afficher une page 404, créez une render_404
méthode (ou not_found
comme je l'ai appelée) ApplicationController
comme ceci:
def not_found
raise ActionController::RoutingError.new('Not Found')
end
Rails gère également AbstractController::ActionNotFound
, et de ActiveRecord::RecordNotFound
la même manière.
Cela fait deux choses mieux:
1) Il utilise le rescue_from
gestionnaire intégré de Rails pour rendre la page 404, et 2) il interrompt l'exécution de votre code, vous permettant de faire de belles choses comme:
user = User.find_by_email(params[:email]) or not_found
user.do_something!
sans avoir à écrire de vilaines instructions conditionnelles.
En prime, il est également très facile à manipuler dans les tests. Par exemple, dans un test d'intégration 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)
Et minitest:
assert_raises(ActionController::RoutingError) do
get '/something/you/want/to/404'
end
OU référez-vous à plus d'informations sur le rendu Rails 404 introuvable à partir d'une action du contrôleur
ActionController::RecordNotFound
c'est la meilleure option?expect { visit '/something/you/want/to/404' }.to raise_error(ActionController::RoutingError)
/ via stackoverflow.com/a/1722839/993890Statut HTTP 404
Pour renvoyer un en-tête 404, utilisez simplement l'
:status
option de la méthode de rendu.Si vous souhaitez rendre la page 404 standard, vous pouvez extraire la fonction dans une méthode.
et appelez-le dans votre action
Si vous souhaitez que l'action affiche la page d'erreur et s'arrête, utilisez simplement une instruction de retour.
ActiveRecord et HTTP 404
N'oubliez pas non plus que Rails récupère certaines erreurs ActiveRecord, telles que l'
ActiveRecord::RecordNotFound
affichage de la page d'erreur 404.Cela signifie que vous n'avez pas besoin de sauver cette action vous-même
User.find
déclenche unActiveRecord::RecordNotFound
lorsque l'utilisateur n'existe pas. Il s'agit d'une fonctionnalité très puissante. Regardez le code suivantVous pouvez le simplifier en déléguant à Rails le chèque. Utilisez simplement la version Bang.
la source
La réponse nouvellement sélectionnée soumise par Steven Soroka est proche, mais pas complète. Le test lui-même cache le fait que cela ne renvoie pas un vrai 404 - il renvoie un statut de 200 - "succès". La réponse d'origine était plus proche, mais a tenté de rendre la mise en page comme si aucune défaillance ne s'était produite. Cela corrige tout:
Voici un ensemble de test typique de la mienne pour quelque chose que je m'attends à retourner 404, en utilisant des matchers RSpec et Shoulda:
Cette paranoïa saine m'a permis de repérer l'inadéquation du type de contenu lorsque tout le reste avait l'air pêche :) Je vérifie tous ces éléments: variables attribuées, code de réponse, type de contenu de la réponse, modèle rendu, mise en page rendue, messages flash.
Je vais sauter la vérification du type de contenu sur les applications strictement html ... parfois. Après tout, "un sceptique vérifie TOUS les tiroirs" :)
http://dilbert.com/strips/comic/1998-01-20/
FYI: Je ne recommande pas de tester les choses qui se produisent dans le contrôleur, c'est-à-dire "should_raise". Ce qui vous intéresse, c'est la sortie. Mes tests ci-dessus m'ont permis d'essayer différentes solutions, et les tests restent les mêmes que la solution lève une exception, un rendu spécial, etc.
la source
render :text => 'Not Found', :status => :not_found
.config.consider_all_requests_local
paramètre défini sur true dans votreenvironments/development.rb
fichier. Si vous soulevez une erreur, comme décrit dans la solution acceptée, dans la mise en scène / production, vous obtiendrez certainement un 404, pas un 200.Vous pouvez également utiliser le fichier de rendu:
Où vous pouvez choisir d'utiliser la mise en page ou non.
Une autre option consiste à utiliser les exceptions pour le contrôler:
la source
La réponse sélectionnée ne fonctionne pas dans Rails 3.1+ car le gestionnaire d'erreurs a été déplacé vers un middleware (voir problème github ).
Voici la solution que j'ai trouvée et qui me satisfait.
Dans
ApplicationController
:et dans
application.rb
:Et dans mes ressources (afficher, éditer, mettre à jour, supprimer):
Cela pourrait certainement être amélioré, mais au moins, j'ai des vues différentes pour not_found et internal_error sans remplacer les fonctions principales de Rails.
la source
|| not_found
partie, il suffit d'appelerfind!
(remarquez le coup) et il lancera ActiveRecord :: RecordNotFound lorsque la ressource ne peut pas être récupérée. Ajoutez également ActiveRecord :: RecordNotFound au tableau dans la condition if.StandardError
et pasException
, juste au cas où. En fait, je vais laisser une page statique standard de 500 et ne pas utiliser du tout de coutumerender_500
, ce qui signifie que je vais explicitement mettre enrescue_from
réseau des erreurs liées à 404ceux-ci vous aideront ...
Contrôleur d'application
Contrôleur d'erreurs
vues / erreurs / error_404.html.haml
la source
il suffit d'ajouter cela à la page que vous souhaitez afficher sur la page d'erreur 404 et vous avez terminé.
la source
Je voulais lancer un 404 `` normal '' pour tout utilisateur connecté qui n'est pas un administrateur, j'ai donc fini par écrire quelque chose comme ça dans Rails 5:
la source
la source
Pour tester la gestion des erreurs, vous pouvez faire quelque chose comme ceci:
la source
Si vous souhaitez gérer différents 404 de différentes manières, pensez à les attraper dans vos contrôleurs. Cela vous permettra de suivre le nombre de 404 générés par différents groupes d'utilisateurs, de faire en sorte que le support interagisse avec les utilisateurs pour découvrir ce qui ne va pas / quelle partie de l'expérience utilisateur pourrait avoir besoin d'être modifiée, faire des tests A / B, etc.
J'ai placé ici la logique de base dans ApplicationController, mais elle peut également être placée dans des contrôleurs plus spécifiques, pour avoir une logique spéciale uniquement pour un contrôleur.
La raison pour laquelle j'utilise un if avec ENV ['RESCUE_404'], c'est pour que je puisse tester l'augmentation de AR :: RecordNotFound de manière isolée. Dans les tests, je peux définir cette var ENV sur false, et mon rescue_from ne se déclencherait pas. De cette façon, je peux tester l'élévation séparément de la logique 404 conditionnelle.
la source