Module: Clutterbuck::Router::ClassMethods

Defined in:
lib/clutterbuck/router.rb

Overview

All of the methods to define the app's routing behaviour are defined on the class, because that's where the config lives. Instances of the app class are created to handle requests.

Instance Method Summary collapse

Instance Method Details

#add_handler(verb, path, &block) ⇒ Object

Define a handler for an arbitrary HTTP method and path.

If more than one handler for a given verb and path match a URL, then the first handler defined will be called.

If no handler matches given path, then 404 Not Found will be returned. If a handler exists for path, but does not support the method of the request, then 405 Method Not Allowed will be returned to the client.

The return value of the block can be one of a number of different things. If you set the Content-Type response header (by calling set_header 'Content-Type', <something>), then no special processing is done and your content is sent to the client more-or-less as-is, with only Content-Length calculation and wrapping your returned object in an array (if it doesn't already respond to #each, as required by Rack). This allows your API to return anything at all if it feels like it.

However, by far the most common response will be a JSON document. If you don't set a Content-Type header in your handler, then we try quite hard to turn what you return from your handler into either JSON (if possible), or text/plain.

For starters, if what you send back responds to #each, then we assume that you know what you're doing and will be sending back strings that will come together to be valid JSON. We'll set Content-Type and Link headers to match with the handler's schema, and that is that.

If what you send back doesn't respond to #each, then we try to determine if its valid JSON by parsing it as JSON (if it's a string) or trying to call #to_json on it. If either of those work, then Content-Type and Link are set to match the schema for your handler, and all is well. Otherwise, we're kinda out of options and we'll send back the content as text/plain and hope the client knows what to do with it.

Parameters:

  • verb (String)

    the case sensitive HTTP method which you wish this handler to respond for. If you're using the get/post/put/etc wrappers foradd_handler`, this argument is taken care of for you. It's only if you want to define your own custom HTTP verbs that you'd ever need to worry about this argument.

  • path (String, Regexp)

    defines the path which is to be handled by this handler. The path is defined relative to the root of the application; that is, there may be path components in the request URI which won't be matched against, because they're handled by the webserver or Rack itself (if the app is routed to via a map block, for example).

    If path is a string, the matching logic is very simple: if the path of the request matches exactly with path, then we run this handler. If not, we skip it.

    If path is a regex, things are ever so slightly more complicated. In that instance, we'll run the handler if the given regex matches the path of the request. In addition, any capturing subexpressions (aka "the bits in parentheses") in the regular expression will be passed as arguments to the handler block.

    In almost all cases, you'll want to anchor your regular expressions (surround them in ^ and $); while it's very unlikely that you'll want to handle a URL with /foo anywhere in the path, we don't want to forbid you from doing so, so there's no automatic anchoring of regexes.

  • block (Proc)

    the code to execute when this handler is invoked. An arbitrary number of arguments may be passed to this block, if path is a regex which contains capturing subexpressions (that is, parts of the regular expression surrounded by unescaped parentheses). This is useful to capture portions of the URL, such as resource IDs, and feed them into your handler as arguments.

Raises:

  • (ArgumentError)

    if you don't pass in a block, or you pass an invalid type for path.



164
165
166
167
168
169
170
171
172
# File 'lib/clutterbuck/router.rb', line 164

def add_handler(verb, path, &block)
	unless block_given?
		raise ArgumentError,
		      "Must pass a block"
	end

	@routes ||= []
	@routes << Route.new(verb, path, method_for(verb, path, block))
end

#call(env) ⇒ Object

Process a request from the app.



30
31
32
# File 'lib/clutterbuck/router.rb', line 30

def call(env)
	self.new(env).call
end

#delete(path, &block) ⇒ Object

Define a handler for DELETE <path> requests.

See #add_handler for all the gory details.

Parameters:

  • path (String, Regexp)
  • block (Proc)

Returns:

  • void



73
74
75
# File 'lib/clutterbuck/router.rb', line 73

def delete(path, &block)
	add_handler('DELETE', path, &block)
end

#find_route(verb, path) ⇒ Object

:nodoc: Grovel through the list of routes, looking for a match.

Raises:



183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/clutterbuck/router.rb', line 183

def find_route(verb, path)
	if @routes.nil?
		raise Clutterbuck::Router::NotFoundError,
		      path
	end

	candidates = @routes.select { |r| r.handles?(path) }

	if candidates.empty?
		raise Clutterbuck::Router::NotFoundError,
		      path
	end

	candidates = candidates.select { |r| r.verb == verb }

	if candidates.empty?
		raise Clutterbuck::Router::MethodNotAllowedError,
		      "#{verb} not permitted on #{path}"
	end

	candidates.first
end

#get(path, &block) ⇒ Object

Define a handler for GET <path> and HEAD <path> requests.

See #add_handler for all the gory details.

Parameters:

  • path (String, Regexp)
  • block (Proc)

Returns:

  • void



48
49
50
51
# File 'lib/clutterbuck/router.rb', line 48

def get(path, &block)
	add_handler('GET', path, &block)
	add_handler('HEAD', path, &block)
end

#patch(path, &block) ⇒ Object

Define a handler for PATCH <path> requests.

See #add_handler for all the gory details.

Parameters:

  • path (String, Regexp)
  • block (Proc)

Returns:

  • void



81
82
83
# File 'lib/clutterbuck/router.rb', line 81

def patch(path, &block)
	add_handler('PATCH', path, &block)
end

#post(path, &block) ⇒ Object

Define a handler for POST <path> requests.

See #add_handler for all the gory details.

Parameters:

  • path (String, Regexp)
  • block (Proc)

Returns:

  • void



65
66
67
# File 'lib/clutterbuck/router.rb', line 65

def post(path, &block)
	add_handler('POST', path, &block)
end

#put(path, &block) ⇒ Object

Define a handler for PUT <path> requests.

See #add_handler for all the gory details.

Parameters:

  • path (String, Regexp)
  • block (Proc)

Returns:

  • void



57
58
59
# File 'lib/clutterbuck/router.rb', line 57

def put(path, &block)
	add_handler('PUT', path, &block)
end