The Dispatcher manages a set of controllers. It selects the appropriate Controller and action to handle the given request.

This dispatcher intelligently handles RESTful uris according to the following scheme:

GET /links GET /links/index Link::Controller#index POST /links POST /links/create Link::Controller#create GET /links;new GET /links/new Link::Controller#new GET /links/1 Link::Controller#view(1) GET /links/1;edit GET /links/edit/1 Link::Controller#edit(1) PUT /links/1 POST /links/update/1 Link::Controller#update DELETE /links/1 GET /links/delete/1 Link::Controller#delete(1) GET /links/index.xml Link::Controller#index # Atom GET /links/index.json Link::Controller#index # JSON

The default actions for the various methods are:

   GET: index
  POST: create
   PUT: update

DELETE: delete

Methods
Attributes
[RW] controllers The hash that maps mount paths to controllers.
[RW] formats The representation formats this dispatcher understands.
[RW] router The (optional) router.
Public Class methods
new(controller_or_map = nil)

Initialize the dispatcher.

    # File lib/raw/dispatcher.rb, line 50
50:   def initialize(controller_or_map = nil)
51:     @controllers = {} 
52:     @formats = Nitro::STANDARD_FORMATS.dup
53:     
54:     if controller_or_map.is_a?(Class)
55:       mount("/" => controller_or_map)
56:     elsif controller_or_map.is_a?(Hash)
57:       mount(controller_or_map)
58:     end 
59:   end
Public Instance methods
[](path = "/")

Return the controller for the given mount path.

    # File lib/raw/dispatcher.rb, line 71
71:   def [](path = "/")
72:     @controllers[path]
73:   end
[]=(path, controller)

Mount a controller to the given mount path.

    # File lib/raw/dispatcher.rb, line 77
77:   def []=(path, controller)
78:     controller = resolve_controller(controller)
79: 
80:     # Customize the class for mounting at the given path.
81:     controller.mount_at(path) if controller.respond_to? :mount_at
82:     
83:     # Call the mounted callback to allow for post mount
84:     # initialization.
85:     controller.mounted(path) if controller.respond_to? :mounted
86: 
87:     @controllers[path] = controller
88:   end
dispatch(uri, method = :get)

Dispatch a path given the request method. This method handles fully resolved paths (containing an extension that denotes the expected content type).

This method automatically handles ‘nice’ (seo friendly, elegant) parameters, ie:

/links/view/1

instead of

/links/view?oid=1

Output

controller, action, query_string, nice_params, extension

     # File lib/raw/dispatcher.rb, line 118
118:   def dispatch(uri, method = :get)
119:     # Extract the query string.
120:     
121:     path, query = uri.split("?", 2)
122: 
123:     # Try to route the path.
124:     
125:     path = @router.route(path) if @router
126: 
127:     # The characters after the last '.' in the path form the 
128:     # extension that itself represents the expected response
129:     # content type.
130:     
131:     ext = File.extname(path)[1..-1] || "html" 
132: 
133:     # The resource representation format for this request.
134:     
135:     unless format = Context.current.format = @formats.by_extension[ext]
136:       raise ActionError.new("Cannot respond to '#{path}' using the '#{ext}' format representation.") 
137:     end
138:     
139:     # Remove the extension from the path.
140:     
141:     path = path.gsub(/\.(.*)$/, '')
142:     
143:     # Try to extract the controller from the path (that may also
144:     # include 'nice' parameters). This algorithm tries to find 
145:     # the bigest substring of the path that represents a mount 
146:     # path for a controller.
147: 
148:     key = path.dup    
149: 
150:     while (controller = @controllers[key]).nil?
151:       key = key[%r{^(/.+)/.+$}, 1] || '/'
152:     end
153: 
154:     # Try to extract the controller from the path. This 
155:     # algorithm tries to find the bigest substring of the path 
156:     # that represents an action of this controller. 
157:     #
158:     # The algorithm respects action name conventions, ie
159:     # simple/sub/action maps to simple__sub__action.
160: 
161:     action = key = path.sub(%r{^#{key}}, '').gsub(%r{^/}, '').gsub(%r{/}, '__')
162: 
163:     while (!action.blank?) and !controller.action_or_template?(action, format)
164:       action = action[%r{^(.+)__.+$}, 1]
165:     end
166: 
167:     # Extract the 'nice' parameters.
168:     
169:     params = key.sub(%r{^#{action}}, '').gsub(/^__/, '').split('__')
170:     
171:     # Do we have an action?
172:     
173:     if action.blank?
174:       # Try to use a standard action for this http method.
175: 
176:       case method
177:         when :get
178:           action = "index"
179:           
180:         when :post
181:           action = "create"
182:             
183:         when :delete
184:           action = "delete"
185:           
186:         when :put
187:           action = "update"
188:       end
189:       
190:       unless controller.action_or_template?(action, format)
191:         raise ActionError.new("Cannot respond to '#{path}' using '#{controller}'") 
192:       end
193:     end
194: 
195:     return controller, "#{action}___super", query, params, ext
196:   end
dispatch_context(request)

Alias for #dispatch_request

dispatch_request(request)

Dispatch a request. Calls the lower level dispatch method.

This method is also aliased as dispatch_context
    # File lib/raw/dispatcher.rb, line 92
92:   def dispatch_request(request)  
93:     dispatch(request.uri, request.method)
94:   end
mount(map)

Mounts a map of controllers.

    # File lib/raw/dispatcher.rb, line 63
63:   def mount(map)
64:     for path, controller in map
65:       self[path] = controller
66:     end
67:   end
root()
    # File lib/raw/dispatcher/mounter.rb, line 52
52:   def root
53:     if controller = self["/"]
54:       Mounter.new(self, controller)
55:     end
56:   end
root=(controller)

An alternative mounting mechanism (CherryPy like).

Example

dispatcher.root = RootController dispatcher.root.users = User::Controller dispatcher.root.users.comments = User::Comment::Controller

    # File lib/raw/dispatcher/mounter.rb, line 48
48:   def root=(controller)
49:     self["/"] = resolve_controller(controller)
50:   end