404 und 500 Fehler in Rails richtig bearbeiten

8. July, 2009 · 1 Kommentar

Die Fehlerausgabe in Ruby on Rails kann manchmal zur Verzweiflung führen. Zwar gibt es von Haus aus die beiden Fehlerdateien “404.html” und “500.html” im public Ordner – was aber tuen, wenn man diese Seiten nicht statisch ausliefern will und stattdessen eine dynamische Fehlerseite generieren möchte.

1. Schritt: Fehlermeldung dynamisch generieren

Seit Rails 2.0 gibt es die praktische Methode rescue_action_in_public(). Diese wird automatisch aufgerufen, wenn beim Rendern der Seite etwas schiefgeht. Dabei ist zu beachten, dass rescue_action_in_public nicht aufgerufen wird, wenn der Request local war. Also nicht wundern, wenn auf dem heimischen Testserver weiterhin die Error Logs angezeigt werden (ist ja auch besser so fürs Debugging).

Eine praktische Anwendung für rescue_action_in_public wäre die folgende (eingefügt in die controller/application.rb damit es global gilt):

  def rescue_action_in_public(exception)
    set_meta("robots","noindex")
    case exception
       when ::ActiveRecord::RecordNotFound
       when ::ActiveRecord::RecordInvalid
       when ::ActionController::RoutingError
       when ::ActionController::UnknownController
       when ::ActionController::UnknownAction
       when ::ActionController::MethodNotAllowed
         render :template => "/general/error_404.html.erb", :status => 404
       else
         render :template => "/general/error_500.html.erb", :status => 500
     end
  end

Der Code ist ja ziemlich selbstsprechend, wenn ein Fehler auftritt, bei dem etwas fehlt (Datenbankeintrag, Action, Methode, etc.) wird ein 404 Fehler ausgegeben (dabei wird hier die Datei “/general/error_404.html.erb” gerendert). Ansonsten die entsprechende 500er Fehlerdatei. Alternativ könnte man natürlich auch einen Redirect auf eine beliebige Seite einbauen.

Noch zu bemerken sei der Befehl set_meta(“robots”,”noindex”) – hier rufe ich die (selbstgeschriebene) Methode zum Setzen des Meta Datensatzes “Robots” auf und gebe dort an, dass die fehlerhafte Seite nicht indiziert werden soll. Damit die Seite nicht trotz eines 404 Status-Codes in einem Suchmaschinenindex landet.

2. Schritt: Statische Dateien löschen

Der Ordnung zu liebe sollte man nun noch die Dateien 404.html und 500.html im public Folder löschen oder zumindest umbenennen, so dass der Webserver diese nicht mehr direkt ausliefert, wenn die URL “http://www.meine-url.de/404.html” geöffnet wird, sei es durch einen Redirect oder sonst wie.

Danach noch die routes.rb im “/config” Ordner um die folgenden Zeilen ergänzen (ganz am Ende einfügen!):

  map.connect '/404.:format', :controller => "/general", :action => "error_404"
  map.connect '/404', :controller => "/general", :action => "error_404"
  map.connect '/500.:format', :controller => "/general", :action => "error_500"
  map.connect '/500', :controller => "/general", :action => "error_500"
  map.connect '*path', :controller => '/general', :action => 'error_404' unless ::ActionController::Base.consider_all_requests_local

Hier werden dann die Direktaufrufe der 404.html und /404 auf das richtige Script umgeleitet. Die letzte Zeile wiederum greift, wenn die aufgerufene URL zu gar keiner anderen Route passt, dann wird ebenfalls die 404 Fehlermeldung gerendert. Letzteres könnte man auch weglassen, denn wenn diese Route nicht da wäre, würde eh ein ActionController::UnknownAction Fehler eintreten und dann greift ja wieder die rescue_action_in_public().

Design Patterns

Natürlich kann man in jeden einzelnen Controller eine eigene rescue_action_in_public Methode einbauen, um so die Fehlerseite möglichst auf den Context anzupassen. So würde es zum Beispiel Sinn machen, in einen Mp3 Controller eine Fehlerseite einzubauen, die den Benutzer informiert, dass das gewünschte Mp3 File nicht vorhanden ist, er sich doch aber die folgenden anderen Songs anhören könnte. Auf diese Weise hält man sich an moderne Designrichtlinien, die genau dies empfehlen: Den Besucher nicht auf einer langweiligen 404-Fehlerseite zurücklassen, sondern stattdessen ihn an die Hand zu nehmen und zu gültigen Inhalten zu führen.

Ihren XING-Kontakten zeigen Artikel bei Xing veröffentlichen
Kategorie:Ruby On Rails · Webdev
Tags: · · · ·

Vorheriger Eintrag: Nächster Eintrag:

  • xbaun

    Hi,
    bin gerade über deinen Beitrag gestolpert und er hat mir auch gleich weitergeholfen 🙂
    Wollt dich nur auf einen Fehler aufmerksam machen, das Ruby bei der case-when Anweisung bei jeder when-Bedingung abbricht die zutrifft und nicht tiefer geht, auch wenn der ausführende Teil leer ist. Also hier schon bei ActiveRecord::RecordNotFound, wenn diese Exception zutrifft und somit wird der render Aufruf erst garnicht ausgeführt.

    mfg

meet me in the interwebs
Kaffee-Kasse
Flattr ist ein sehr gut gemachter Micropayment Dienst, der es endlich ermöglicht auf faire Weise Geld zu spenden und einzunehmen.