Class: Watts::App

Inherits:
Object
  • Object
show all
Defined in:
lib/watts.rb

Overview

In order to have a Watts app, you’ll want to subclass Watts::App. For a good time, you’ll also probably want to provide some resources to that class using the resource method, which maps paths to resources.

Constant Summary collapse

Errors =
{
	400 =>
		[400, {'Content-Type' => 'text/plain'}, ["400 Bad Request.\n"]],
	404 =>
		[404, {'Content-Type' => 'text/plain'}, ["404 Not Found\n"]],
	501 =>
		[501, {'Content-Type' => 'text/plain'},
			["501 Not Implemented.\n"]],
}
ESet =

The “empty” set.

Set.new(['/', ''])
MNCache =

Method name cache. Maps HTTP methods to object methods.

Hash.new { |h,k|
	h[k] = k.downcase.to_sym
}

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Class Attribute Details

.path_stack=(value) ⇒ Object (writeonly)

Sets the attribute path_stack

Parameters:

  • value

    the value to set the attribute path_stack to.



94
95
96
# File 'lib/watts.rb', line 94

def path_stack=(value)
  @path_stack = value
end

Class Method Details

.decypher_path(p) ⇒ Object



97
98
99
100
101
102
# File 'lib/watts.rb', line 97

def self.decypher_path p
return p if p.kind_of?(Array)
return [] if ESet.include?(p)
return [p] if p.kind_of?(Regexp) || p.kind_of?(Symbol)
p.split('/').tap { |a| a.reject!(&''.method(:'==')) }
end

.path_to(res, *args) ⇒ Object

Given a resource (and, optionally, arguments if the path requires them), this method returns an absolute path to the resource.



159
160
161
# File 'lib/watts.rb', line 159

def self.path_to res, *args
	path_map.rmatch res, args
end

.resource(path, res = nil, &b) ⇒ Object Also known as: res

If you want your Watts application to do anything at all, you’re very likely to want to call this method at least once. The basic purpose of the method is to tell your app how to match a resource to a path. For example, if you create a resource (see Watts::Resource) Foo, and you want requests against ‘/foo’ to match it, you could do this: resource(‘foo’, Foo)

The first argument is the path, and the second is the resource that path is to match. (Please see the README for more detailed documentation of path-matching.) You may also pass it a block, in which resources that are defined are ‘namespaced’. For example, if you also had a resource called Bar and wanted its path to be a sub-path of the Foo resource’s (e.g., ‘/foo/bar’), then typing these lines is a pretty good plan: resource(‘foo’, Foo) { resource(‘bar’, Bar) }

Lastly, the resource argument itself is optional, for when you want a set of resources to be namespaced under a given path, but don’t have a resource in mind. For example, if you suddenly needed your entire application to reside under ‘/api’, you could do this: resource(‘api’) {

	resource('foo', Foo) {

resource(‘bar’, Bar) resource(‘baz’, Baz) } }

This is probably the most important method in Watts. Have a look at the README and the example applications under doc/examples if you want to understand the pattern-matching, arguments to resources, etc.



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/watts.rb', line 138

def self.resource(path, res = nil, &b)
	path = decypher_path(path)

	last = (path_stack + path).inject(path_map) { |m,p|
		m[p] ||= Path.new
	}
	last.resource = res

	if b
		old_stack = path_stack
		self.path_stack = old_stack + path
		b.call
		self.path_stack = old_stack
	end
	res
end

Instance Method Details

#call(env, req_path = nil) ⇒ Object

Our interaction with Rack.



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/watts.rb', line 170

def call env, req_path = nil
	rm = MNCache[env['REQUEST_METHOD']]
	return(Errors[501]) unless Resource::HTTPMethods.include?(rm)

	req_path ||= decypher_path env['PATH_INFO']
	resource_class, args = path_map.match req_path, []

	if resource_class
		env[:watts_app] ||= self
		res = resource_class.new env
		res.send(rm, *args)
	else
		Errors[404]
	end
end

#match(req_path) ⇒ Object

Given a path, returns the matching resource, if any.



164
165
166
167
# File 'lib/watts.rb', line 164

def match req_path
	req_path = decypher_path req_path
	path_map.match req_path, []
end