Class: Merb::Dispatcher

Inherits:
Object show all
Defined in:
lib/merb-core/dispatch/dispatcher.rb

Constant Summary collapse

DEFAULT_ERROR_TEMPLATE =
File.expand_path(File.dirname(__FILE__) / 'exceptions.html')
@@mutex =
Mutex.new

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.use_mutexObject

Returns the value of attribute use_mutex.



6
7
8
# File 'lib/merb-core/dispatch/dispatcher.rb', line 6

def use_mutex
  @use_mutex
end

Class Method Details

.handle(rack_env) ⇒ Object

This is where we grab the incoming request REQUEST_URI and use that in the merb RouteMatcher to determine which controller and method to run. Returns a 2 element tuple of: [controller, action]

ControllerExceptions are rescued here and redispatched.

Parameters

rack_env<Rack::Environment>

The rack environment, which is used to instantiate a Merb::Request

response<IO>

An IO object to hold the response

Returns

Array[Merb::Controller, Symbol]

An array containing the Merb::Controller and the action that was dispatched to.



27
28
29
30
31
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/merb-core/dispatch/dispatcher.rb', line 27

def handle(rack_env)
  start   = Time.now
  request = Merb::Request.new(rack_env)
  
  route_index, route_params = Merb::Router.match(request)
  
  if route_params.empty?
    raise ::Merb::ControllerExceptions::NotFound, "No routes match the request, #{request.uri}"
  end
  request.route_params = route_params
  request.params.merge! route_params
  
  Merb.logger.info("Params: #{request.params.inspect}")
  
  controller_name = (route_params[:namespace] ? route_params[:namespace] + '/' : '') + route_params[:controller]
  
  unless controller_name
    raise Merb::ControllerExceptions::NotFound, "Route matched, but route did not specify a controller" 
  end
  
  Merb.logger.debug("Routed to: #{request.route_params.inspect}")

  cnt = controller_name.snake_case.to_const_string
  
  if !Merb::Controller._subclasses.include?(cnt)
    raise Merb::ControllerExceptions::NotFound, "Controller '#{cnt}' not found"
  end
  if cnt == "Application"
    raise Merb::ControllerExceptions::NotFound, "The 'Application' controller has no public actions"
  end

  begin
    klass = Object.full_const_get(cnt)
  rescue NameError
    raise Merb::ControllerExceptions::NotFound
  end

  action = route_params[:action]

  controller = dispatch_action(klass, action, request)
  controller._benchmarks[:dispatch_time] = Time.now - start
  controller.route = Merb::Router.routes[route_index] if route_index
  Merb.logger.info controller._benchmarks.inspect
  Merb.logger.flush

  controller
# this is the custom dispatch_exception; it allows failures to still be dispatched
# to the error controller
rescue => exception
  Merb.logger.error(Merb.exception(exception))
  unless request.xhr?
    exception = controller_exception(exception)
    dispatch_exception(request, exception)
  else
    Struct.new(:headers, :status, :body).new({}, 500,
      <<-HERE
#{exception.message}
 
Params:
#{(request.params || {}).map { |p,v| "  #{p}: #{v}\n"}.join("\n")}
 
Session:
#{(request.session || {}).map { |p,v| "  #{p}: #{v}\n"}.join("\n")}
 
Cookies:
#{(request.cookies || {}).map { |p,v| "  #{p}: #{v}\n"}.join("\n")}
 
Stacktrace:
#{exception.backtrace.join("\n")}
      HERE
    )
  end
end