bats 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +16 -0
- data/lib/bats.rb +87 -0
- data/lib/bats/modules/classbaker.rb +26 -0
- data/lib/bats/modules/httpresponse.rb +36 -0
- data/lib/bats/modules/metaid.rb +16 -0
- data/lib/bats/modules/wizarding.rb +28 -0
- data/lib/bats/yaml/statuses.yaml +17 -0
- metadata +70 -0
data/README
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
~~~(^._.^)~~~ Bats!
|
2
|
+
|
3
|
+
A micro-framework.
|
4
|
+
|
5
|
+
Bats! implements an easy to use router on top of Rack for handling REST
|
6
|
+
requests. This makes getting an app up and running ridiculously easy.
|
7
|
+
|
8
|
+
Bats! stays out of your way. It doesn't ask you to use any particular
|
9
|
+
development methodology, templating framework, or other such tom-foolery.
|
10
|
+
|
11
|
+
Example usage:
|
12
|
+
|
13
|
+
# config.ru
|
14
|
+
|
15
|
+
require 'bats'
|
16
|
+
|
data/lib/bats.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
%w( httpresponse wizarding ).each do |f|
|
2
|
+
require 'bats/modules/httpresponse'
|
3
|
+
end
|
4
|
+
|
5
|
+
class Bats
|
6
|
+
extend Wizarding
|
7
|
+
|
8
|
+
traits :routes
|
9
|
+
|
10
|
+
def self.inherited c
|
11
|
+
c.traits *traits.keys
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.addRoute m, p, o = nil, &b
|
15
|
+
@traits[ :routes ] ||= {}
|
16
|
+
@traits[ :routes ][ m ] ||= {}
|
17
|
+
@traits[ :routes ][ m ][ p ] = ( block_given? ) ? b : o
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.get p, o = nil, &b; addRoute( :get, p, o, &b ); end
|
21
|
+
def self.post p, o = nil, &b; addRoute( :post, p, o, &b ); end
|
22
|
+
def self.put p, o = nil, &b; addRoute( :put, p, o, &b ); end
|
23
|
+
def self.delete p, o = nil, &b; addRoute( :delete, p, o, &b ); end
|
24
|
+
|
25
|
+
def self.redirect l, isTemporary = true
|
26
|
+
i = ( isTemporary ) ? '307' : '301'
|
27
|
+
statusCode( i ).headers( :Location => l )
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.call env; new.call( env ); end
|
31
|
+
|
32
|
+
def statusCode i
|
33
|
+
::HTTPResponse.const_get( "Status#{i}" )
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.statusCode i
|
37
|
+
::HTTPResponse.const_get( "Status#{i}" )
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.pubDir
|
41
|
+
File.expand_path( '../../public', __FILE__ )
|
42
|
+
end
|
43
|
+
|
44
|
+
def pubDir
|
45
|
+
File.expand_path( '../../public', __FILE__ )
|
46
|
+
end
|
47
|
+
|
48
|
+
def call env
|
49
|
+
method = env[ 'REQUEST_METHOD' ].downcase.to_sym
|
50
|
+
path = env[ 'PATH_INFO' ]
|
51
|
+
matches ||= nil
|
52
|
+
if @routes && @routes[method] then
|
53
|
+
if @routes[method].include?( path ) then
|
54
|
+
route = @routes[method][ path ]
|
55
|
+
else
|
56
|
+
@routes[method].each do | p, b |
|
57
|
+
if p.kind_of?( Regexp ) then
|
58
|
+
if matches = path.match( p ) then
|
59
|
+
matches = matches[ 1, matches.length - 1 ]
|
60
|
+
matches.map! do | i |
|
61
|
+
i = ( i ) ? i : ''
|
62
|
+
i = i.to_i if i =~ /^[\d]+$/
|
63
|
+
i
|
64
|
+
end
|
65
|
+
route = b
|
66
|
+
break # Eh! give me a break here!
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
if !route && path =~ /\./ then
|
73
|
+
route = ::Rack::File.new( pubDir ) if File.exist?( "#{pubDir}/#{path}" )
|
74
|
+
end
|
75
|
+
route ||= statusCode( 404 )
|
76
|
+
args = ( matches ) ? [ env, *matches ] : [ env ]
|
77
|
+
begin
|
78
|
+
route = route.call( args ) if route.kind_of?( Proc )
|
79
|
+
route.call( env )
|
80
|
+
rescue
|
81
|
+
b = '<h1>Ooops... The code broke.</h1>'
|
82
|
+
b += "<h3>#{$!.to_s}</h3>#{$!.backtrace.join( '<br/>' )}"
|
83
|
+
route = statusCode(500).body b
|
84
|
+
route.call( env )
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
%w( metaid wizarding ).each { | f | require "bats/modules/#{f}" }
|
2
|
+
|
3
|
+
module ClassBaker
|
4
|
+
include Metaid
|
5
|
+
|
6
|
+
def makeClass n, c = nil
|
7
|
+
c = ( c.nil? ) ? Class.new : c
|
8
|
+
c = ( c.is_a?( String ) ) ? Class.new( const_get( c ) ) : c
|
9
|
+
const_set n, c
|
10
|
+
c
|
11
|
+
end
|
12
|
+
|
13
|
+
def bakeClass h
|
14
|
+
h.each do | c, o |
|
15
|
+
t = o.include?( :inherit ) ? o[ :inherit ] : nil
|
16
|
+
o.delete( :inherit )
|
17
|
+
i = makeClass( c, t )
|
18
|
+
i.extend( Wizarding )
|
19
|
+
unless o.empty? then
|
20
|
+
i.traits *o.keys
|
21
|
+
o.each { | k, v | i.send( k, v ) }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'bats/modules/classbaker'
|
2
|
+
|
3
|
+
module HTTPResponse
|
4
|
+
extend ClassBaker
|
5
|
+
|
6
|
+
class Response
|
7
|
+
extend ::Wizarding
|
8
|
+
|
9
|
+
traits :status, :headers, :body
|
10
|
+
|
11
|
+
def self.headers h
|
12
|
+
@traits[ :headers ] ||= {}
|
13
|
+
@traits[ :headers ].merge!( h )
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.call env; new.call( env ); end
|
17
|
+
|
18
|
+
def call env
|
19
|
+
[ @status, @headers, @body ]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'yaml'
|
24
|
+
statuses = YAML.load_file( "#{File.expand_path( '../yaml', File.dirname( __FILE__ ) )}/statuses.yaml" ) # Somewhere in the nether regions beyond column 80!
|
25
|
+
statuses.each do | k, v |
|
26
|
+
bakeClass(
|
27
|
+
"Status#{k}" => {
|
28
|
+
:inherit => 'Response',
|
29
|
+
:status => k,
|
30
|
+
:headers => v[0],
|
31
|
+
:body => v[1]
|
32
|
+
}
|
33
|
+
)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Sorry _why I don't feel like extending Ruby's Object class.
|
2
|
+
module Metaid
|
3
|
+
def metaclass; class << self; self; end; end
|
4
|
+
|
5
|
+
def meta_eval &b
|
6
|
+
metaclass.instance_eval &b
|
7
|
+
end
|
8
|
+
|
9
|
+
def meta_def( n, &b )
|
10
|
+
meta_eval { define_method( n, &b ) }
|
11
|
+
end
|
12
|
+
|
13
|
+
def class_def( n, &b )
|
14
|
+
class_eval { define_method( n, &b ) }
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'bats/modules/metaid'
|
2
|
+
|
3
|
+
module Wizarding
|
4
|
+
include Metaid
|
5
|
+
|
6
|
+
def traits *a
|
7
|
+
return @traits if a.empty?
|
8
|
+
attr_accessor *a
|
9
|
+
a.each do | m |
|
10
|
+
@traits ||= {}
|
11
|
+
@traits[m] = nil
|
12
|
+
meta_def m do | *v |
|
13
|
+
@traits[m] = v[0] unless v.empty?
|
14
|
+
( v.empty? ) ? @traits[m] : self
|
15
|
+
end
|
16
|
+
end
|
17
|
+
class_def :initialize do
|
18
|
+
self.class.traits.each do | k, v |
|
19
|
+
instance_variable_set( "@#{k}", v )
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def inherited c
|
25
|
+
c.traits *traits.keys
|
26
|
+
c.instance_variable_set( :@traits, traits.dup )
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
404:
|
2
|
+
- Content-Type: text/plain
|
3
|
+
- '404: Page not found.'
|
4
|
+
301:
|
5
|
+
- Content-Type: text/html
|
6
|
+
Location: '/'
|
7
|
+
- '301: Moved Permanently.'
|
8
|
+
307:
|
9
|
+
- Content-Type: text/html
|
10
|
+
Location: '/'
|
11
|
+
- '307: Moved Temporarily.'
|
12
|
+
200:
|
13
|
+
- Content-Type: text/html
|
14
|
+
- '200: Page Successfully Loaded.'
|
15
|
+
500:
|
16
|
+
- Content-Type: text/html
|
17
|
+
- '500: Oh noes... an error.'
|
metadata
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bats
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Hans Oksendahl
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-10-07 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rack
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
description:
|
26
|
+
email: hansoksendahl@gmail.com
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- README
|
33
|
+
files:
|
34
|
+
- lib/bats.rb
|
35
|
+
- lib/bats/yaml/statuses.yaml
|
36
|
+
- lib/bats/modules/httpresponse.rb
|
37
|
+
- lib/bats/modules/classbaker.rb
|
38
|
+
- lib/bats/modules/wizarding.rb
|
39
|
+
- lib/bats/modules/metaid.rb
|
40
|
+
- README
|
41
|
+
has_rdoc: true
|
42
|
+
homepage: http://hansoksendahl.com/
|
43
|
+
licenses: []
|
44
|
+
|
45
|
+
post_install_message:
|
46
|
+
rdoc_options: []
|
47
|
+
|
48
|
+
require_paths:
|
49
|
+
- - lib
|
50
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: "0"
|
55
|
+
version:
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: "0"
|
61
|
+
version:
|
62
|
+
requirements: []
|
63
|
+
|
64
|
+
rubyforge_project:
|
65
|
+
rubygems_version: 1.3.5
|
66
|
+
signing_key:
|
67
|
+
specification_version: 3
|
68
|
+
summary: A microframework built on Rack.
|
69
|
+
test_files: []
|
70
|
+
|