Il existe de nombreuses solutions pour créer des pages de gestion des erreurs personnalisées, mais presque aucune pour Rails 4:
La réponse standard d'encourager les gens à modifier 404.html
dans /public
ne fonctionne pas pour moi car je souhaite utiliser le thème CSS qui réside dans le pipeline des ressources. Existe-t-il un moyen pour les fichiers html d'accéder aux styles définis dans le pipeline d'actifs? Sinon, existe-t-il moyen de créer un gestionnaire d'erreurs personnalisé qui a accès au pipeline?
Pour Rails 4.1 J'aime cette réponse, ajoutez un type d'actif mieux; mais je ne l'ai pas essayé. Sur Rails 4.0. 8, ces trois références m'ont aidé:
Pages d'erreur dynamiques est la deuxième référence dans la question. Cela a très bien fonctionné pour moi.
Pages d'erreur personnalisées peut avoir été corrigé à partir de la première référence, ou l'inverse, mais va plus loin en ajoutant des informations sur les tests avec Capybara.
Je n'ai pas fait le test Capybara parce que je ne voulais pas changer la configuration du test; cependant, RSpec-Rails Request Specs m'a demandé de tester ces demandes indépendamment et de voir qu'elles se terminent et renvoient le contenu correct.
Ce qui suit est une description en bref de ce qui est enseigné par les trois références:
Ajoutez le paramètre suivant à config/environments/production.rb
# Route exceptions to the application router vs. default
config.exceptions_app = self.routes
Modifiez la configuration de routage, config/routes.rb
pour diriger les pages d'erreur vers un contrôleur d'erreurs
# error pages
%w( 404 422 500 503 ).each do |code|
get code, :to => "errors#show", :code => code
end
achemine les demandes de pages 404, 422, 500 et 503 vers l'action show
du contrôleur errors
avec un paramètre code
qui a la valeur du code d'état.
Créez le contrôleur, app/controllers/errors_controller.rb
. Voici tout le contenu:
class ErrorsController < ApplicationController
def show
status_code = params[:code] || 500
flash.alert = "Status #{status_code}"
render status_code.to_s, status: status_code
end
end
Ma préférence était de définir un message d'état sur flash.alert
Créez les pages elles-mêmes. J'utilise .erb
Voici app/views/errors/500.html.erb
<p>Our apology. Your request caused an error.</p>
<%= render 'product_description' %>
Vous voyez donc que vous pouvez rendre un partiel. La page s'affiche avec tous les passe-partout de mise en page de app/views/layouts/application.html.erb
ou tout autre passe-partout de disposition que vous avez configuré. Cela inclut le <div id='alert'><%= alert %></div>
qui affiche le message d'état du flash.
Testé avec RSpec en ajoutant un fichier de test, spec/requests/errors_request_spec.rb
. Voici le contenu abrégé de ce fichier qui montre un test de la page d'état 500:
require 'Rails_helper'
RSpec.describe "errors", :type => :request do
it "displays the 500 page" do
get "/500"
assert_select 'div#alert', 'Status 500'
assert_select 'div[itemtype]'
end
end
La première assertion vérifie l'alerte flash. La deuxième assertion vérifie le partiel.
Nous avons fait un bijou qui fait cela pour vous: exception_handler
.
Il y a aussi un excellent tutoriel ici .
J'ai également écrit une réponse détaillée sur le sujet ici .
Middleware
# config/application.rb
config.exceptions_app = ->(env) { ExceptionController.action(:show).call(env) }
Contrôleur
# app/controllers/exception_controller.rb
class ExceptionController < ApplicationController
respond_to :json, :js, :html
before_action :set_status
def show
respond_with @status
end
private
def set_status
def status
@exception = env['action_dispatch.exception']
@status = ActionDispatch::ExceptionWrapper.new(env, @exception).status_code
@response = ActionDispatch::ExceptionWrapper.rescue_responses[@exception.class.name]
end
end
end
Voir
# app/views/exception/show.html.erb
<h1>404 error</h1>
Ceci est une version très simple - je peux vous expliquer plus si vous le souhaitez.
Fondamentalement, vous devez vous connecter au config.exceptions_app
middleware, il capturera toute exception dans la pile middleware
(par opposition au rendu de l'environnement entier), vous permettant d'envoyer la demande à votre propre controller#action
.
Si vous commentez, je vais vous aider un peu plus si vous le souhaitez!