bats 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+
@@ -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
+