gnarly 0.0.2 → 0.0.3

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.
@@ -1,28 +1,81 @@
1
- require 'gnarly/provides.rb'
2
1
  require 'gnarly/url.rb'
2
+ require 'gnarly/environment.rb'
3
3
 
4
4
  module Gnarly
5
5
 
6
6
  class Application
7
- include Provides
7
+ include Status
8
8
 
9
9
  def initialize()
10
10
  @urls = []
11
+ @environment = Environment.new self
12
+ end
13
+
14
+ def init(&block)
15
+ @environment.instance_exec &block
11
16
  end
12
17
 
13
18
  def url(url_mask, &block)
14
19
  url = Url.new(url_mask)
15
- url.instance_eval &block
20
+ url.instance_eval &block if block
16
21
  @urls << url
22
+ url
23
+ end
24
+
25
+ def helper(helper)
26
+ (@helpers ||= []) << helper
17
27
  end
18
28
 
19
- def call(env)
20
- environment env
29
+ def get(*args, &block)
30
+ m = args.shift
31
+ u = url m
32
+ u.get *args, &block
33
+ end
34
+
35
+ def put(*args, &block)
36
+ m = args.shift
37
+ u = url m
38
+ u.put *args, &block
39
+ end
40
+
41
+ def post(*args, &block)
42
+ m = args.shift
43
+ u = url m
44
+ u.post *args, &block
45
+ end
46
+
47
+ def delete(*args, &block)
48
+ m = args.shift
49
+ u = url m
50
+ u.delete *args, &block
51
+ end
52
+
53
+ def call(state)
54
+ environment = @environment.dup
55
+ environment.extend *@helpers if @helpers
56
+ environment.state state
57
+ request = environment.request
21
58
  path = request.path
22
59
  if url = @urls.detect { |u| u.match? path }
23
60
  @responder = url.responder request.method
24
61
  if @responder
25
- instance_exec *url.parameters, &@responder
62
+ helpers = url.helpers
63
+ environment.extend *helpers if helpers
64
+ if before = url.before
65
+ environment.instance_exec *url.parameters, &before
66
+ end
67
+ keys = url.keys request.method
68
+ response = environment.instance_exec *url.parameters(*keys), &@responder
69
+ if after = url.after
70
+ environment.instance_exec *url.parameters, &after
71
+ end
72
+ unless response.is_a? Array and response.size == 3
73
+ name, line = @responder.source_location
74
+ msg = "Bad return type for block in #{name} line #{line}"
75
+ internal_server_error msg
76
+ else
77
+ response
78
+ end
26
79
  else
27
80
  method_not_allowed url.allow
28
81
  end
@@ -31,6 +84,8 @@ module Gnarly
31
84
  end
32
85
  end
33
86
 
87
+ private
88
+
34
89
  end
35
90
 
36
91
  def self.application(&block)
data/lib/gnarly/base.rb CHANGED
@@ -4,16 +4,20 @@ module Gnarly
4
4
 
5
5
  module Base
6
6
 
7
- def environment(env=nil)
8
- if env
9
- @environment = env
7
+ def state(state=nil)
8
+ if state
9
+ @state = state
10
10
  @request = nil
11
11
  end
12
- @environment
12
+ @state
13
13
  end
14
14
 
15
15
  def request()
16
- @request ||= Request.new @environment
16
+ @request ||= Request.new @state
17
+ end
18
+
19
+ def logger()
20
+ @state["rack.logger"]
17
21
  end
18
22
 
19
23
  def body_charset(body)
@@ -0,0 +1,21 @@
1
+ require 'gnarly/provides.rb'
2
+ require 'gnarly/understands.rb'
3
+
4
+ module Gnarly
5
+
6
+ class Environment
7
+ include Provides
8
+ include Understands
9
+
10
+ def initialize(app)
11
+ @application = app
12
+ push_default_content_type "text/plain"
13
+ end
14
+
15
+ def application()
16
+ @application
17
+ end
18
+
19
+ end
20
+
21
+ end
@@ -0,0 +1,40 @@
1
+ require 'haml'
2
+
3
+ module Gnarly
4
+
5
+ module Haml
6
+
7
+ def haml(name, &block)
8
+ root = application.haml_root
9
+ template = File.read "#{root}/#{name}.haml"
10
+ engine = ::Haml::Engine.new template
11
+ body = engine.render self
12
+ if block
13
+ push_default_content_type "text/html"
14
+ result = block.call body
15
+ pop_default_content_type
16
+ result
17
+ else
18
+ body
19
+ end
20
+ end
21
+
22
+ end
23
+
24
+ class Application
25
+
26
+ def haml_root(haml_root=nil)
27
+ if haml_root
28
+ @haml_root = haml_root
29
+ else
30
+ @haml_root ||= "haml"
31
+ end
32
+ end
33
+
34
+ end
35
+
36
+ class Environment
37
+ include Haml
38
+ end
39
+
40
+ end
@@ -11,25 +11,15 @@ module Gnarly
11
11
  def provides(*mimes, &block)
12
12
  mime = MIMEParse.best_match mimes, request.accept
13
13
  if mime
14
+ push_default_content_type mime
14
15
  response = block.call mime if block
15
- if response.is_a? Array and response.size == 3
16
- status, headers, body = response
17
- unless headers.key? "Content-type"
18
- charset = body_charset(body)
19
- headers["Content-type"] =
20
- charset ? "#{mime}; charset=#{charset}" : mime
21
- end
22
- response
23
- else
24
- name, line = @responder.source_location
25
- msg = "Bad return type for block in #{filename} line #{line}"
26
- internal_server_error msg
27
- end
16
+ pop_default_content_type
17
+ response
28
18
  else
29
19
  not_acceptable
30
20
  end
31
21
  end
32
-
22
+
33
23
  end
34
-
24
+
35
25
  end
@@ -3,22 +3,23 @@ require 'rack/utils'
3
3
  module Gnarly
4
4
 
5
5
  class Request
6
+ attr_reader :state
6
7
 
7
- def initialize(env)
8
- @environment = env
8
+ def initialize(state)
9
+ @state = state
9
10
  parse_content_type
10
11
  end
11
12
 
12
13
  def path()
13
- @path ||= @environment["PATH_INFO"]
14
+ @path ||= @state["PATH_INFO"]
14
15
  end
15
16
 
16
17
  def method()
17
- @method ||= @environment["REQUEST_METHOD"]
18
+ @method ||= @state["REQUEST_METHOD"].downcase.to_sym
18
19
  end
19
20
 
20
21
  def accept()
21
- @accept ||= @environment["HTTP_ACCEPT"]
22
+ @accept ||= @state["HTTP_ACCEPT"]
22
23
  end
23
24
 
24
25
  def content_type()
@@ -31,7 +32,7 @@ module Gnarly
31
32
 
32
33
  def body()
33
34
  unless @body
34
- input = @environment["rack.input"]
35
+ input = @state["rack.input"]
35
36
  @body = input.read
36
37
  input.rewind
37
38
  @body.force_encoding charset if charset
@@ -40,14 +41,14 @@ module Gnarly
40
41
  end
41
42
 
42
43
  def params()
43
- @params ||= ::Rack::Utils.parse_query(@environment["QUERY_STRING"])
44
+ @params ||= ::Rack::Utils.parse_query(@state["QUERY_STRING"])
44
45
  end
45
46
 
46
47
  private
47
48
 
48
49
  def parse_content_type()
49
- if header = @environment["CONTENT_TYPE"]
50
- header =~ /^([^;\s]+)(\s*;\s*charset=(\S+)\s*)$/
50
+ if header = @state["CONTENT_TYPE"]
51
+ header =~ /^([^;\s]+)(\s*;\s*charset=(\S+)\s*)?$/
51
52
  @content_type = $1
52
53
  @charset = $3
53
54
  end
data/lib/gnarly/status.rb CHANGED
@@ -3,11 +3,29 @@ module Gnarly
3
3
 
4
4
  module Status
5
5
 
6
+ def push_default_content_type(mime)
7
+ (@default_content_types ||= []).push mime
8
+ end
9
+
10
+ def pop_default_content_type()
11
+ @default_content_types.pop if @default_content_types
12
+ end
13
+
14
+ def default_content_type()
15
+ @default_content_types.last if @default_content_types
16
+ end
17
+
6
18
  def ok(body, mime=nil)
19
+ mime = default_content_type unless mime
7
20
  headers = mime ? {"Content-type" => mime} : {}
8
21
  [200, headers, [body]]
9
22
  end
10
23
 
24
+ def created(location)
25
+ headers = {"Location" => location, "Content-type" => "text/plain"}
26
+ [201, headers, [""]]
27
+ end
28
+
11
29
  def not_found(body="Not Found", mime="text/plain")
12
30
  [404, {"Content-type" => mime}, [body]]
13
31
  end
@@ -25,6 +43,10 @@ module Gnarly
25
43
  [body]]
26
44
  end
27
45
 
46
+ def unsupported_media_type(body="Unsupported Media Type", mime="text/plain")
47
+ [415, {"Content-type" => mime}, [body]]
48
+ end
49
+
28
50
  def internal_server_error(body="Internal Server Error", mime="text/plain")
29
51
  [500, {"Content-type" => mime}, [body]]
30
52
  end
@@ -0,0 +1,35 @@
1
+
2
+ module Gnarly
3
+
4
+ class System
5
+
6
+ def initialize(*apps)
7
+ @apps = apps
8
+ end
9
+
10
+ def +(app)
11
+ @apps << app
12
+ self
13
+ end
14
+
15
+ def call(env)
16
+ response = nil
17
+ @apps.find do |app|
18
+ response = app.call(env)
19
+ status = response.first
20
+ status != 404 and status < 500
21
+ end
22
+ response
23
+ end
24
+
25
+ end
26
+
27
+ class Application
28
+
29
+ def +(other)
30
+ System.new self, other
31
+ end
32
+
33
+ end
34
+
35
+ end
@@ -0,0 +1,21 @@
1
+ require 'gnarly/base.rb'
2
+ require 'gnarly/status.rb'
3
+
4
+ module Gnarly
5
+
6
+ module Understands
7
+ include Base
8
+ include Status
9
+
10
+ def understands(*mimes, &block)
11
+ mime = MIMEParse.best_match [request.content_type], mimes.join(",")
12
+ if mime
13
+ block.call mime if block
14
+ else
15
+ unsupported_media_type
16
+ end
17
+ end
18
+
19
+ end
20
+
21
+ end
data/lib/gnarly/url.rb CHANGED
@@ -4,50 +4,147 @@ module Gnarly
4
4
  class Url
5
5
 
6
6
  def initialize(url_mask)
7
- @url_mask = url_mask
7
+ case url_mask
8
+ when String
9
+ @url_mask = make_url_mask url_mask
10
+ when Regexp
11
+ @url_mask = url_mask
12
+ end
8
13
  @responders = {}
14
+ @keys = {}
9
15
  @allow = []
10
16
  end
11
17
 
12
18
  def match?(path)
13
- @match = @url_mask.match path
19
+ @match = @url_mask.match path if @url_mask
14
20
  @match != nil
15
21
  end
16
22
 
17
- def parameters()
18
- a = @match.to_a
19
- a.shift
20
- a
23
+ def parameters(*keys)
24
+ if keys.empty?
25
+ a = @match.to_a
26
+ a.shift
27
+ if @types
28
+ (0..a.size - 1).collect do |i|
29
+ case @types[i]
30
+ when :integer
31
+ a[i].to_i
32
+ else
33
+ a[i]
34
+ end
35
+ end
36
+ else
37
+ a
38
+ end
39
+ else
40
+ if @type_map
41
+ keys.collect do |key|
42
+ case @type_map[key.to_s]
43
+ when :integer
44
+ @match[key].to_i
45
+ else
46
+ @match[key]
47
+ end
48
+ end
49
+ else
50
+ keys.collect do |key|
51
+ @match[key]
52
+ end
53
+ end
54
+ end
21
55
  end
22
56
 
23
57
  def responder(method)
24
58
  @responders[method]
25
59
  end
26
60
 
61
+ def keys(method)
62
+ @keys[method]
63
+ end
64
+
27
65
  def allow()
28
66
  @allow.join " "
29
67
  end
30
68
 
31
- def get(&block)
32
- @responders["GET"] = block
69
+ def helper(helper)
70
+ (@helpers ||= []) << helper
71
+ end
72
+
73
+ def helpers()
74
+ @helpers
75
+ end
76
+
77
+ def get(*keys, &block)
78
+ @responders[:get] = block
79
+ @keys[:get] = keys
33
80
  @allow << "GET"
34
81
  end
35
82
 
36
- def put(&block)
37
- @responders["PUT"] = block
83
+ def put(*keys, &block)
84
+ @responders[:put] = block
85
+ @keys[:put] = keys
38
86
  @allow << "PUT"
39
87
  end
40
88
 
41
- def post(&block)
42
- @responders["POST"] = block
89
+ def post(*keys, &block)
90
+ @responders[:post] = block
91
+ @keys[:post] = keys
43
92
  @allow << "POST"
44
93
  end
45
94
 
46
- def delete(&block)
47
- @responders["DELETE"] = block
95
+ def delete(*keys, &block)
96
+ @responders[:delete] = block
97
+ @keys[:delete] = keys
48
98
  @allow << "DELETE"
49
99
  end
50
100
 
101
+ def before(&block)
102
+ if block
103
+ @before = block
104
+ else
105
+ @before
106
+ end
107
+ end
108
+
109
+ def after(&block)
110
+ if block
111
+ @after = block
112
+ else
113
+ @after
114
+ end
115
+ end
116
+
117
+ def make_url_mask(template)
118
+ types = []
119
+ type_map = {}
120
+ has_types = false
121
+ s = template.gsub(/\{([^\}]*)\}/) do
122
+ name, type = $1.split ":"
123
+ t = nil
124
+ p = case type
125
+ when "integer", "index"
126
+ has_types = true
127
+ t = :integer
128
+ types << t
129
+ '\d+'
130
+ else
131
+ types << nil
132
+ '[^/]+'
133
+ end
134
+ nc = ""
135
+ if name and name != ""
136
+ nc = "?<#{name}>"
137
+ type_map[name] = t
138
+ end
139
+ "(#{nc}#{p})"
140
+ end
141
+ if has_types
142
+ @types = types
143
+ @type_map = type_map
144
+ end
145
+ Regexp.new "^#{s}$"
146
+ end
147
+
51
148
  end
52
149
 
53
150
  end
data/lib/gnarly.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'gnarly/application.rb'
2
+ require 'gnarly/system.rb'
2
3
 
3
4
  module Gnarly
4
5
 
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 2
9
- version: 0.0.2
8
+ - 3
9
+ version: 0.0.3
10
10
  platform: ruby
11
11
  authors:
12
12
  - Kim Dalsgaard
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-02-25 00:00:00 +01:00
17
+ date: 2010-03-08 00:00:00 +01:00
18
18
  default_executable:
19
19
  dependencies: []
20
20
 
@@ -29,10 +29,14 @@ extra_rdoc_files: []
29
29
  files:
30
30
  - lib/gnarly/application.rb
31
31
  - lib/gnarly/base.rb
32
+ - lib/gnarly/environment.rb
33
+ - lib/gnarly/haml.rb
32
34
  - lib/gnarly/mimeparse.rb
33
35
  - lib/gnarly/provides.rb
34
36
  - lib/gnarly/request.rb
35
37
  - lib/gnarly/status.rb
38
+ - lib/gnarly/system.rb
39
+ - lib/gnarly/understands.rb
36
40
  - lib/gnarly/url.rb
37
41
  - lib/gnarly/uuid.rb
38
42
  - lib/gnarly.rb