Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Changeset 5504

Show
Ignore:
Timestamp:
11/13/06 02:03:50 (2 years ago)
Author:
bitsweat
Message:

test controller rescues

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/actionpack/lib/action_controller/rescue.rb

    r5243 r5504  
    11module ActionController #:nodoc: 
    2   # Actions that fail to perform as expected throw exceptions. These exceptions can either be rescued for the public view  
     2  # Actions that fail to perform as expected throw exceptions. These exceptions can either be rescued for the public view 
    33  # (with a nice user-friendly explanation) or for the developers view (with tons of debugging information). The developers view 
    44  # is already implemented by the Action Controller, but the public view should be tailored to your specific application. So too 
     
    77  # You can tailor the rescuing behavior and appearance by overwriting the following two stub methods. 
    88  module Rescue 
     9    LOCALHOST = '127.0.0.1'.freeze 
     10 
     11    DEFAULT_RESCUE_RESPONSE = :internal_server_error 
     12    DEFAULT_RESCUE_RESPONSES = { 
     13      'ActionController::RoutingError'    => :not_found, 
     14      'ActionController::UnknownAction'   => :not_found 
     15    } 
     16 
     17    DEFAULT_RESCUE_TEMPLATE = 'diagnostics' 
     18    DEFAULT_RESCUE_TEMPLATES = { 
     19      'ActionController::MissingTemplate' => 'missing_template', 
     20      'ActionController::RoutingError'    => 'routing_error', 
     21      'ActionController::UnknownAction'   => 'unknown_action', 
     22      'ActionView::TemplateError'         => 'template_error' 
     23    } 
     24 
    925    def self.included(base) #:nodoc: 
     26      base.cattr_accessor :rescue_responses 
     27      base.rescue_responses = Hash.new(DEFAULT_RESCUE_RESPONSE) 
     28      base.rescue_responses.update DEFAULT_RESCUE_RESPONSES 
     29 
     30      base.cattr_accessor :rescue_templates 
     31      base.rescue_templates = Hash.new(DEFAULT_RESCUE_TEMPLATE) 
     32      base.rescue_templates.update DEFAULT_RESCUE_TEMPLATES 
     33 
    1034      base.extend(ClassMethods) 
    1135      base.class_eval do 
     
    3963        else 
    4064          logger.fatal( 
    41             "\n\n#{exception.class} (#{exception.message}):\n    " +  
    42             clean_backtrace(exception).join("\n    ") +  
     65            "\n\n#{exception.class} (#{exception.message}):\n    " + 
     66            clean_backtrace(exception).join("\n    ") + 
    4367            "\n\n" 
    4468          ) 
     
    4670      end 
    4771 
     72 
    4873      # Overwrite to implement public exception handling (for requests answering false to <tt>local_request?</tt>). 
    4974      def rescue_action_in_public(exception) #:doc: 
    50         case exception 
    51           when RoutingError, UnknownAction 
    52             render_text(IO.read(File.join(RAILS_ROOT, 'public', '404.html')), "404 Not Found") 
    53           else 
    54             render_text(IO.read(File.join(RAILS_ROOT, 'public', '500.html')), "500 Internal Error") 
     75        render_optional_error_file response_code_for_rescue(exception) 
     76      end 
     77 
     78      def render_optional_error_file(status_code) #:nodoc: 
     79        status = interpret_status(status_code) 
     80        path = "#{RAILS_ROOT}/public/#{status[0,3]}.html" 
     81        if File.exists?(path) 
     82          render :file => path, :status => status 
     83        else 
     84          head status 
    5585        end 
    5686      end 
    5787 
    58       # Overwrite to expand the meaning of a local request in order to show local rescues on other occurrences than 
    59       # the remote IP being 127.0.0.1. For example, this could include the IP of the developer machine when debugging 
    60       # remotely
     88      # True if the request came from localhost, 127.0.0.1. Override this 
     89      # method if you wish to redefine the meaning of a local request to 
     90      # include remote IP addresses or other criteria
    6191      def local_request? #:doc: 
    62         [request.remote_addr, request.remote_ip] == ["127.0.0.1"] * 2 
     92        request.remote_addr == LOCALHOST and request.remote_ip == LOCALHOST 
    6393      end 
    6494 
    65       # Renders a detailed diagnostics screen on action exceptions.  
     95      # Render detailed diagnostics for unhandled exceptions rescued from 
     96      # a controller action. 
    6697      def rescue_action_locally(exception) 
    6798        add_variables_to_assigns 
    6899        @template.instance_variable_set("@exception", exception) 
    69         @template.instance_variable_set("@rescues_path", File.dirname(rescues_path("stub")))     
     100        @template.instance_variable_set("@rescues_path", File.dirname(rescues_path("stub"))) 
    70101        @template.send(:assign_variables_from_controller) 
    71102 
    72103        @template.instance_variable_set("@contents", @template.render_file(template_path_for_local_rescue(exception), false)) 
    73      
     104 
    74105        response.content_type = Mime::HTML 
    75106        render_file(rescues_path("layout"), response_code_for_rescue(exception)) 
    76107      end 
    77      
     108 
    78109    private 
    79110      def perform_action_with_rescue #:nodoc: 
    80         begin 
    81           perform_action_without_rescue 
    82         rescue Exception => exception  # errors from action performed 
    83           if defined?(Breakpoint) && params["BP-RETRY"] 
    84             msg = exception.backtrace.first 
    85             if md = /^(.+?):(\d+)(?::in `(.+)')?$/.match(msg) then 
    86               origin_file, origin_line = md[1], md[2].to_i 
     111        perform_action_without_rescue 
     112      rescue Exception => exception  # errors from action performed 
     113        if defined?(Breakpoint) && params["BP-RETRY"] 
     114          msg = exception.backtrace.first 
     115          if md = /^(.+?):(\d+)(?::in `(.+)')?$/.match(msg) then 
     116            origin_file, origin_line = md[1], md[2].to_i 
    87117 
    88               set_trace_func(lambda do |type, file, line, method, context, klass| 
    89                 if file == origin_file and line == origin_line then 
    90                   set_trace_func(nil) 
    91                   params["BP-RETRY"] = false 
     118            set_trace_func(lambda do |type, file, line, method, context, klass| 
     119              if file == origin_file and line == origin_line then 
     120                set_trace_func(nil) 
     121                params["BP-RETRY"] = false 
    92122 
    93                   callstack = caller 
    94                   callstack.slice!(0) if callstack.first["rescue.rb"] 
    95                   file, line, method = *callstack.first.match(/^(.+?):(\d+)(?::in `(.*?)')?/).captures 
     123                callstack = caller 
     124                callstack.slice!(0) if callstack.first["rescue.rb"] 
     125                file, line, method = *callstack.first.match(/^(.+?):(\d+)(?::in `(.*?)')?/).captures 
    96126 
    97                   message = "Exception at #{file}:#{line}#{" in `#{method}'" if method}." # `Ž ( for ruby-mode) 
     127                message = "Exception at #{file}:#{line}#{" in `#{method}'" if method}." # `Ž ( for ruby-mode) 
    98128 
    99                   Breakpoint.handle_breakpoint(context, message, file, line) 
    100                 end 
    101               end) 
     129                Breakpoint.handle_breakpoint(context, message, file, line) 
     130              end 
     131            end) 
    102132 
    103               retry 
    104             end 
     133            retry 
    105134          end 
     135        end 
    106136 
    107           rescue_action(exception) 
    108         end 
     137        rescue_action(exception) 
    109138      end 
    110139 
    111140      def rescues_path(template_name) 
    112         File.dirname(__FILE__) + "/templates/rescues/#{template_name}.rhtml" 
     141        "#{File.dirname(__FILE__)}/templates/rescues/#{template_name}.rhtml" 
    113142      end 
    114143 
    115144      def template_path_for_local_rescue(exception) 
    116         rescues_path( 
    117           case exception 
    118             when MissingTemplate then "missing_template" 
    119             when RoutingError then "routing_error" 
    120             when UnknownAction   then "unknown_action" 
    121             when ActionView::TemplateError then "template_error" 
    122             else "diagnostics" 
     145        rescues_path(rescue_templates[exception.class.name]) 
     146      end 
     147 
     148      def response_code_for_rescue(exception) 
     149        rescue_responses[exception.class.name] 
     150      end 
     151 
     152      def clean_backtrace(exception) 
     153        if backtrace = exception.backtrace 
     154          if defined?(RAILS_ROOT) 
     155            backtrace.map { |line| line.sub RAILS_ROOT, '' } 
     156          else 
     157            backtrace 
    123158          end 
    124         ) 
    125       end 
    126        
    127       def response_code_for_rescue(exception) 
    128         case exception 
    129           when UnknownAction, RoutingError  
    130             "404 Page Not Found" 
    131           else 
    132             "500 Internal Error" 
    133159        end 
    134       end 
    135        
    136       def clean_backtrace(exception) 
    137         exception.backtrace.collect { |line| Object.const_defined?(:RAILS_ROOT) ? line.gsub(RAILS_ROOT, "") : line } 
    138160      end 
    139161  end 
  • trunk/actionpack/lib/action_controller/templates/rescues/_request_and_response.rhtml

    r5241 r5504  
    1111    <%= form_tag(request.request_uri, "method" => request.method) %> 
    1212      <input type="hidden" name="BP-RETRY" value="1" /> 
    13    
     13 
    1414      <% for key, values in params %> 
    1515        <% next if key == "BP-RETRY" %> 
     
    2727 
    2828<% 
    29   request_parameters_without_action = request.parameters.clone 
    30   request_parameters_without_action.delete("action") 
    31   request_parameters_without_action.delete("controller") 
    32    
    33   request_dump = request_parameters_without_action.inspect.gsub(/,/, ",\n") 
     29  clean_params = request.parameters.clone 
     30  clean_params.delete("action") 
     31  clean_params.delete("controller") 
     32 
     33  request_dump = clean_params.empty? ? 'None' : clean_params.inspect.gsub(',', ",\n") 
    3434%> 
    3535 
    3636<h2 style="margin-top: 30px">Request</h2> 
    37 <p><b>Parameters</b>: <%=h request_dump == "{}" ? "None" : request_dump %></p> 
     37<p><b>Parameters</b>: <pre><%=h request_dump %></pre></p> 
    3838 
    3939<p><a href="#" onclick="document.getElementById('session_dump').style.display='block'; return false;">Show session dump</a></p> 
     
    4242 
    4343<h2 style="margin-top: 30px">Response</h2> 
    44 <b>Headers</b>: <%=h response ? response.headers.inspect.gsub(/,/, ",\n") : "None" %><br/
     44<p><b>Headers</b>: <pre><%=h response ? response.headers.inspect.gsub(',', ",\n") : 'None' %></pre></p