root/trunk/lib/merb/exceptions.rb

Revision 1073, 9.3 kB (checked in by e.@brainspl.at, 1 year ago)

few touch ups

Line 
1 begin
2   require 'coderay'
3 rescue LoadError => ex
4 end
5
6 module Merb
7   # ControllerExceptions are a way of simplifying controller code by placing
8   # exceptional logic back into the MVC pattern.
9   #
10   # When a ControllerException is raised within your application merb will
11   # attempt to re-route the request to your Exceptions controller to render
12   # the error in a friendly mannor.
13   #
14   # For example you might have an action in your app that raises NotFound
15   # if a some resource was not available
16   #
17   #   def show
18   #     product = Product.find(params[:id])
19   #     raise NotFound if product.nil?
20   #     [...]
21   #   end
22   #
23   # This would halt execution of your action and re-route it over to your
24   # Exceptions controller which might look something like
25   #
26   # class Exceptions < Application
27   #   def not_found
28   #     render :layout => :none
29   #   end
30   # end
31   #
32   # As usual the not_found action will look for a template in
33   #   app/views/exceptions/not_found.html.erb
34   #
35   # Note: All standard ControllerExceptions have an HTTP status code associated
36   # with them which is sent to the browser when the action it is rendered.
37   #
38   # Note: If you do not specifiy how to handle raised ControllerExceptions
39   # or an unhandlable exception occurs within your customised exception action
40   # then they will be rendered using the built-in error template
41   # in development mode this "built in" template will show stack-traces for
42   # any of the ServerError family of exceptions (you can force the stack-trace
43   # to display in production mode using the :exception_details config option in
44   # merb.yml)
45   #
46   #
47   # Internal Exceptions
48   #
49   # Any other rogue errors (not ControllerExceptions) that occur during the
50   # execution of you app will be converted into the ControllerException
51   # InternalServerError, and like all ControllerExceptions can be caught
52   # on your Exceptions controller.
53   #
54   # InternalServerErrors return status 500, a common use for cusomizing this
55   # action might be to send emails to the development team, warning that their
56   # application have exploded. Mock example:
57   #
58   #   def internal_server_error
59   #     MySpecialMailer.deliver(
60   #       "team@cowboys.com",
61   #       "Exception occured at #{Time.now}",
62   #       params[:exception])
63   #     render :inline => 'Something is wrong, but the team are on it!'
64   #   end
65   #
66   # Note: The special param[:exception] is available in all Exception actions
67   # and contains the ControllerException that was raised (this is handy if
68   # you want to display the associated message or display more detailed info)
69   #
70   #
71   # Extending ControllerExceptions
72   #
73   # To extend the use of the ControllerExceptions one may extend any of the
74   # HTTPError classes.
75   #
76   # As an example we can create an exception called AdminAccessRequired.
77   #
78   #   class AdminAccessRequired < Merb::ControllerExceptions::Unauthorized; end
79   #
80   # Add the required action to our Exceptions controller
81   #
82   #   class Exceptions < Application
83   #     def admin_access_required
84   #       render
85   #     end
86   #   end
87   #
88   # In app/views/exceptions/admin_access_required.rhtml
89   #
90   #   <h1>You're not an administrator!</h1>
91   #   <p>You tried to access <%= @tried_to_access %> but that URL is
92   #   restricted to administrators.</p>
93   #
94   module ControllerExceptions
95    
96     # Mapping of status code names to their numeric value.
97     STATUS_CODES = {}
98    
99     class Base < StandardError
100       def name
101         self.class.to_s.snake_case.split('::').last
102       end
103      
104       #
105       # Registers any subclasses with status codes for easy lookup by
106       # set_status in Merb::Controller.
107       #
108       # Inheritance ensures this method gets inherited by any subclasses, so
109       # it goes all the way down the chain of inheritance.
110       #
111       def self.inherited(subclass)
112         if subclass.const_defined?(:STATUS)
113           STATUS_CODES[subclass.name.snake_case.to_sym] = subclass.const_get(:STATUS)
114         end
115       end
116     end
117    
118     class Informational                 < Merb::ControllerExceptions::Base; end
119       class Continue                    < Merb::ControllerExceptions::Informational; STATUS = 100; end
120       class SwitchingProtocols          < Merb::ControllerExceptions::Informational; STATUS = 101; end
121     class Successful                    < Merb::ControllerExceptions::Base; end
122       class OK                          < Merb::ControllerExceptions::Successful; STATUS = 200; end
123       class Created                     < Merb::ControllerExceptions::Successful; STATUS = 201; end
124       class Accepted                    < Merb::ControllerExceptions::Successful; STATUS = 202; end
125       class NonAuthoritativeInformation < Merb::ControllerExceptions::Successful; STATUS = 203; end
126       class NoContent                   < Merb::ControllerExceptions::Successful; STATUS = 204; end
127       class ResetContent                < Merb::ControllerExceptions::Successful; STATUS = 205; end
128       class PartialContent              < Merb::ControllerExceptions::Successful; STATUS = 206; end
129     class Redirection                   < Merb::ControllerExceptions::Base; end
130       class MultipleChoices             < Merb::ControllerExceptions::Redirection; STATUS = 300; end
131       class MovedPermanently            < Merb::ControllerExceptions::Redirection; STATUS = 301; end
132       class MovedTemporarily            < Merb::ControllerExceptions::Redirection; STATUS = 302; end
133       class SeeOther                    < Merb::ControllerExceptions::Redirection; STATUS = 303; end
134       class NotModified                 < Merb::ControllerExceptions::Redirection; STATUS = 304; end
135       class UseProxy                    < Merb::ControllerExceptions::Redirection; STATUS = 305; end
136       class TemporaryRedirect           < Merb::ControllerExceptions::Redirection; STATUS = 307; end
137     class ClientError                   < Merb::ControllerExceptions::Base; end
138       class BadRequest                  < Merb::ControllerExceptions::ClientError; STATUS = 400; end
139         class MultiPartParseError       < Merb::ControllerExceptions::BadRequest; end
140       class Unauthorized                < Merb::ControllerExceptions::ClientError; STATUS = 401; end
141       class PaymentRequired             < Merb::ControllerExceptions::ClientError; STATUS = 402; end
142       class Forbidden                   < Merb::ControllerExceptions::ClientError; STATUS = 403; end
143       class NotFound                    < Merb::ControllerExceptions::ClientError; STATUS = 404; end
144         class ActionNotFound            < Merb::ControllerExceptions::NotFound; end
145         class TemplateNotFound          < Merb::ControllerExceptions::NotFound; end
146         class LayoutNotFound            < Merb::ControllerExceptions::NotFound; end
147       class MethodNotAllowed            < Merb::ControllerExceptions::ClientError; STATUS = 405; end
148       class NotAcceptable               < Merb::ControllerExceptions::ClientError; STATUS = 406; end
149       class ProxyAuthenticationRequired < Merb::ControllerExceptions::ClientError; STATUS = 407; end
150       class RequestTimeout              < Merb::ControllerExceptions::ClientError; STATUS = 408; end
151       class Conflict                    < Merb::ControllerExceptions::ClientError; STATUS = 409; end
152       class Gone                        < Merb::ControllerExceptions::ClientError; STATUS = 410; end
153       class LengthRequired              < Merb::ControllerExceptions::ClientError; STATUS = 411; end
154       class PreconditionFailed          < Merb::ControllerExceptions::ClientError; STATUS = 412; end
155       class RequestEntityTooLarge       < Merb::ControllerExceptions::ClientError; STATUS = 413; end
156       class RequestURITooLarge          < Merb::ControllerExceptions::ClientError; STATUS = 414; end
157       class UnsupportedMediaType        < Merb::ControllerExceptions::ClientError; STATUS = 415; end
158       class RequestRangeNotSatisfiable  < Merb::ControllerExceptions::ClientError; STATUS = 416; end
159       class ExpectationFailed           < Merb::ControllerExceptions::ClientError; STATUS = 417; end
160     class ServerError                   < Merb::ControllerExceptions::Base; end
161       class NotImplemented              < Merb::ControllerExceptions::ServerError; STATUS = 501; end
162       class BadGateway                  < Merb::ControllerExceptions::ServerError; STATUS = 502; end
163       class ServiceUnavailable          < Merb::ControllerExceptions::ServerError; STATUS = 503; end
164       class GatewayTimeout              < Merb::ControllerExceptions::ServerError; STATUS = 504; end
165       class HTTPVersionNotSupported     < Merb::ControllerExceptions::ServerError; STATUS = 505; end
166       class InternalServerError         < Merb::ControllerExceptions::ServerError;
167         STATUS = 500
168         DEFAULT_TEMPLATE = ::Merb::Dispatcher::DEFAULT_ERROR_TEMPLATE
169      
170         def initialize(exception = nil)
171           @exception = exception
172           @coderay = CodeRay rescue nil
173         end
174      
175         def backtrace
176           @exception ? @exception.backtrace : backtrace
177         end
178      
179         def message
180           @exception ? @exception.message : message
181         end
182       end
183   end
184  
185   # PLEASE STOP REMOVING THIS ONE GUYS! It's used to show exceptions in the log file
186   # this is the second time I've had to add it back.
187   def self.exception(e)
188     "#{ e.message } - (#{ e.class })\n" << 
189     "#{(e.backtrace or []).join("\n")}"
190   end
191
192 end 
Note: See TracBrowser for help on using the browser.