Class: Ramaze::Dispatcher::Error

Inherits:
Object
  • Object
show all
Defined in:
lib/ramaze/dispatcher/error.rb

Overview

Last resort dispatcher, tries to recover as much information as possible from the past request and takes the appropiate actions.

You can configure it over the HANDLE_ERROR constant or by defining error actions in your controllers.

Constant Summary collapse

HANDLE_ERROR =

The class of exception is matched when an error occurs and the status code is set. The absolute URLs are used as fallback in case of a total failure.

{
                    Exception => [ 500, '/error' ],
      Ramaze::Error::NoAction => [ 404, '/error' ],
  Ramaze::Error::NoController => [ 404, '/error' ],
}

Class Method Summary collapse

Class Method Details

.call(error, metainfo = {}) ⇒ Object

Takes exception, of metainfo only :controller is used at the moment. Then goes on to try and find the correct response status and path. In case metainfo has a controller we try to get the action for the path on it, dispatching there if we find one. Otherwise a plain-text error message is set as response.



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/ramaze/dispatcher/error.rb', line 32

def call(error, metainfo = {})
  log_error(error)

  Thread.current[:exception] = error
  response = Response.current

  key = error.class.ancestors.find{|a| HANDLE_ERROR[a]}
  status, path = *HANDLE_ERROR[key || Exception]
  status ||= 500

  if controller = metainfo[:controller]
    newpath = (controller.mapping + path).squeeze('/')
    action_response = Dispatcher::Action.call(newpath)
    case action_response
    when Ramaze::Error
      Log.debug("No custom error page found on #{controller}, going to #{path}")
    else
      action_response.status = status
      return action_response
    end
  end

  if path and Global.error_page and error.message !~ /`#{path}'/
    response.status = status
    return Dispatcher.dispatch_to(path)
  else
    response.build(error.message, status)
  end
rescue Object => ex
  Log.error(ex)
  begin
    m = ex.message
    c = ex.class
    b = [ex.backtrace].flatten.join("\n")
    body = <<-html
    ==== Error ====\n
      #{ m } (#{ c })
      #{ b }\n
    ==== Request ====\n
      #{ Request.current.pretty }\n
    ==== Request ====\n
      #{ Response.current.pretty }\n
    ==== Session ====\n
      #{ Session.current.pretty }\n
    ==== Global ====\n
      #{ Global.pretty }\n
    html
    response['Content-Type'] = 'text/plain'
    response.build(body.unindent, status)
  rescue Object
    raise
  end
end

.currentObject

Handle to current exception. Only works inside request/response cycle.



101
102
103
# File 'lib/ramaze/dispatcher/error.rb', line 101

def current
  Thread.current[:exception]
end

.log_error(error) ⇒ Object

Only logs new errors with full backtrace, repeated errors are shown only with their message.



88
89
90
91
92
93
94
95
96
97
# File 'lib/ramaze/dispatcher/error.rb', line 88

def log_error error
  error_message = error.message

  if trait[:last_error] == error_message or error.is_a? Ramaze::Error::NoAction
    Log.error(error_message)
  else
    trait[:last_error] = error_message
    Log.error(error)
  end
end