2 # Created by Matt Todd on 2008-01-02.
3 # Copyright (c) 2007. All rights reserved.
11 %w(rubygems merb/core_ext merb/router).each {|dep|require dep}
13 abort "Merb must be installed for Routing to function. Please install Merb."
30 # r.match('/path/to/match').to(:action => 'do_stuff')
31 # {:action => 'not_found'} # the default route
33 # def do_stuff(params)
40 # Supplying a default route if none of the others match is good practice,
41 # but is unnecessary as the predefined route is always, automatically,
42 # going to contain a redirection to the +not_found+ method. (So your app
43 # should implement a +not_found+ method.)
45 # In order to set a different default route, simply end the call to +route+
46 # with a hash containing the action to run along with any other params.
50 # The mechanics of the router are solely from the efforts of the Merb
51 # community. This functionality is completely ripped right out of Merb
52 # and makes it functional. All credit to them, and be sure to check out
53 # their great framework: if you need a beefier framework, maybe Merb is
56 # http://merbivore.com/
57 class MRouter < Merb::Router
64 env['merb.router'] = self
65 env['merb.route'] = self.class.route(env)
69 # Retrieves the last value from the +route+ call and, if it's a Hash, sets
70 # it to +@@default_route+ to designate the failover route. If +route+ is
71 # not a Hash, though, the internal default should be used instead (as the
72 # last returned value is probably a Route object returned by the
73 # <tt>r.match().to()</tt> call).
75 # Used exclusively internally.
76 def self.default_to route
77 @@default_route = route.is_a?(Hash) ? route : {:action => 'not_found'}
80 # Called internally by the +call+ method to match the current request
81 # against the currently defined routes. Returns the params list defined in
82 # the +to+ routing definition, opting for the default route if no match is
85 # pull out the path requested (WEBrick keeps the host and port and protocol in REQUEST_URI)
86 uri = URI.parse(env['REQUEST_URI']).path
89 path = (uri ? uri.split('?').first : '').sub(/\/+/, '/')
90 path = path[0..-2] if (path[-1] == ?/) && path.size > 1
91 req = Struct.new(:path, :method).new(path, env['REQUEST_METHOD'].downcase.to_sym)
94 route = self.match(req, {})
96 # make sure a route is returned even if no match is found
101 # params (including action and module if set) for the matching route
109 # The Helper that provides the +route+ class method and +route+ instance method
110 # to setup routes and to actually route the request.
113 # Matches the request information in +env+ to the appropriate route.
115 Rack::MRouter.route(@env)
119 # Yields the router which allows routes to be set up.
122 Rack::MRouter.prepare do |router|
123 Rack::MRouter.default_to yield(router)
126 abort "Halcyon::Server::Base.route expects a block to define routes."
131 # Hook to include the class methods into the receiver.
132 def self.included(receiver)
133 receiver.extend(ClassMethods)