scytrin-maveric 2 → 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.
Files changed (2) hide show
  1. data/lib/maveric.rb +120 -82
  2. metadata +1 -1
data/lib/maveric.rb CHANGED
@@ -3,85 +3,22 @@ require 'uri'
3
3
  require 'rack'
4
4
 
5
5
  module Maveric
6
- class Response < Exception
7
- DEFAULT, @r = [500, 'text/plain'], {}
8
- def self.[] e; @r[e]; end
9
- def self.[]= e, v; @r[e]=v; end
10
- def initialize err
11
- @status, @headers, @body = if resp = Response[err] then resp else
12
- [ DEFAULT[0],
13
- { 'Content-Type' => DEFAULT[1],
14
- 'Content-Length' => err.length.to_s },
15
- err]
16
- end
17
- super @body
18
- end
19
- def each; @body.each{|line| yield line }; end
20
- def to_a; [@status, @headers, self]; end # to_splat in 1.9
21
- alias_method :finish, :to_a
22
- end
23
-
24
- module Views
25
- attr_reader :maveric
26
- TEMPLATES = {}
27
- end
28
-
29
- module Helpers
30
- protected
31
-
32
- # Powerhouse method to build a response. TODO: doc
33
- def respond *args, &blk
34
- headers = Hash === args.last ? args.pop : {}
35
- seed = (Symbol === args.last && args.last) ? '' : args.pop
36
- views, args = args.reverse.partition{|e| Symbol === e }
37
-
38
- bad = views.map{|e|e.to_s} - self.class::Views.instance_methods
39
- raise ArgumentError, 'Invalid views: '+bad.inspect unless bad.empty?
40
- warn 'Invalid arguments: '+args.inspect unless args.empty?
41
-
42
- response = Rack::Response.new
43
- response.headers.update self.class.headers
44
- response.headers.update headers.
45
- reject{|(k,v)| !k.is_a? String or !v.is_a? String }
46
- response.extend self.class::Views
47
- response.instance_variable_set '@maveric', self
48
-
49
- catch :response do
50
- yield response if block_given?
51
- body = views.inject(seed){|b,v| response.__send__(v,b) }.to_s
52
- response.length = Rack::Utils.bytesize body
53
- response.body = body.to_a
54
- return response.finish
55
- end
56
- end
57
-
58
- private
59
-
60
- # Provides a simple way of generating a redirection response, relative to
61
- # the current url.
62
- def redirect uri
63
- uri = URI(uri).normalize
64
- uri = URI(@request.url).merge uri
65
- [ 303, { 'Location'=>uri.to_s,
66
- 'Content-Type'=>'text/plain',
67
- 'Content-Length'=>'0'
68
- }, [] ]
69
- end
70
- end
6
+ # Should contain methods to be shared amongst various maverics
7
+ module Helpers; end
71
8
 
9
+ # Should contain various views to be utilized by various maverics
10
+ module Views; attr_reader :maveric; TEMPLATES = {}; end
72
11
 
73
12
 
74
13
  # The current instance is stored in the passed environment under the key
75
14
  # 'maveric'. A Rack::Request of the current request is provided at @request.
76
- #
77
- # If no action is provided, @action is set as :index.
78
- def initialize env, action=nil, route=nil
15
+ def initialize env
79
16
  env['maveric'] = self
80
17
  @request = Rack::Request.new env
81
- @route, @action = route, action || :index
18
+ @route, @action = self.class.routes.empty? ?
19
+ [nil, :index] : self.class.routes.find{|(r,d)| r === env['PATH_INFO'] }
82
20
  extend self.class::Helpers
83
21
  self.init_hook if self.respond_to? :init_hook
84
- p [ @request.script_name, @route, @action ]
85
22
  end
86
23
  attr_reader :request, :route, :action
87
24
 
@@ -110,12 +47,68 @@ module Maveric
110
47
  end
111
48
 
112
49
 
50
+ private
51
+
52
+
53
+ # Powerhouse method to build a response. TODO: doc
54
+ def respond *args, &blk
55
+ headers = Hash === args.last ? args.pop : {}
56
+ seed = (Symbol === args.last && args.last) ? '' : args.pop
57
+ views, args = args.reverse.partition{|e| Symbol === e }
58
+
59
+ bad = views.map{|e|e.to_s} - self.class::Views.instance_methods
60
+ raise ArgumentError, 'Invalid views: '+bad.inspect unless bad.empty?
61
+ warn 'Invalid arguments: '+args.inspect unless args.empty?
62
+
63
+ response = Rack::Response.new
64
+ response.headers.update self.class.headers
65
+ response.headers.update headers.
66
+ reject{|(k,v)| !k.is_a? String or !v.is_a? String }
67
+ response.extend self.class::Views
68
+ response.instance_variable_set '@maveric', self
69
+
70
+ catch :response do
71
+ yield response if block_given?
72
+ body = views.inject(seed){|b,v| response.__send__(v,b) }.to_s
73
+ response.length = Rack::Utils.bytesize body
74
+ response.body = body.to_a
75
+ return response.finish
76
+ end
77
+ end
78
+
79
+
80
+ # Provides a simple way of generating a redirection response, relative to
81
+ # the current url.
82
+ def redirect uri
83
+ uri = URI(uri).normalize
84
+ uri = URI(@request.url).merge uri
85
+ [ 303, { 'Location'=>uri.to_s,
86
+ 'Content-Type'=>'text/plain',
87
+ 'Content-Length'=>'0'
88
+ }, [] ]
89
+ end
90
+
91
+
92
+ def routes_to dest
93
+ self.class.routes.select{|(r,d)| d === dest }
94
+ end
95
+
96
+
97
+ def route_to dest
98
+ routes_to(dest).find{|(r,d)| String === d }
99
+ end
100
+
101
+
102
+
113
103
  # Methods provided to construct a maveric
114
104
  module Class
115
105
  # Default headers for Maveric instantiation.
116
106
  attr_reader :routes, :headers
117
107
  attr_writer :mount
118
108
 
109
+ # Scours through './templates', unless provided an alternate directory,
110
+ # and adds templates and a method to maveric::Views. Currently handles
111
+ # haml and erb files.
119
112
  def add_templates directory='templates/*'
120
113
  Dir.glob directory do |file| p file
121
114
  next unless File.readable? file and tmpl = File.read(file)
@@ -143,9 +136,15 @@ module Maveric
143
136
  end
144
137
  end
145
138
 
139
+ # Instantiates a maveric with the provided environment, then calls
140
+ # maveric#response
146
141
  def call env
147
- r, a = @routes.find{|(r,d)| r === env['PATH_INFO'] }
148
- new(env, a, r).response
142
+ new(env).response
143
+ end
144
+
145
+ def routing mountpoint, routes
146
+ @mount = mountpoint
147
+ routes.each{|d,a| route d, *a }
149
148
  end
150
149
 
151
150
  def route d, *a
@@ -156,25 +155,32 @@ module Maveric
156
155
  @mount || self.name.downcase.gsub(/^|::/, '/')
157
156
  end
158
157
 
159
- def inspect
160
- "#<Maveric:#{self.name} '#{mount}'>"
161
- end
162
-
163
158
  def self.extend_object obj
164
159
  obj.instance_variable_set '@routes', []
165
160
  obj.instance_variable_set '@headers', Rack::Utils::HeaderHash.new
166
161
  super
167
162
  end
163
+
164
+ def inspect
165
+ "#{self.name}:'#{mount}':#{routes.inspect}"
166
+ end
168
167
  end
169
168
 
169
+
170
+
170
171
  @maverics = [] unless defined? @maverics
171
172
  @last_hash = nil
172
173
  @map = nil
173
174
  class << self
174
175
  attr_reader :maverics
175
176
 
177
+ def inspect
178
+ "Maveric#{maverics.inspect}"
179
+ end
180
+
176
181
  # Generates a Rack::URLMap compatible hash composed of all maverics and
177
- # their mount points.
182
+ # their mount points. Will be regenerated if the list of maverics have
183
+ # changed.
178
184
  def map
179
185
  return @map if @map and @last_hash == @maverics.hash
180
186
  @last_hash = @maverics.hash
@@ -195,7 +201,9 @@ module Maveric
195
201
  self.urlmap.call env
196
202
  end
197
203
 
198
- def new app
204
+ # Returns itself, or a Rack::Cascade when provided an app
205
+ def new app=nil
206
+ return self unless app
199
207
  Rack::Cascade.new [app, self]
200
208
  end
201
209
 
@@ -226,15 +234,42 @@ module Maveric
226
234
  return obj
227
235
  end
228
236
  end
237
+
238
+
239
+
240
+ # Response is an Exception class that can be raised from within a call to
241
+ # maveric#response, with 401, 403, and 404 errors provided.
242
+ #
243
+ # <tt>raise Maveric::Response, 404</tt> will look up 404 via Response#[] and
244
+ # if a value is found, it is utilized to set the status, headers, and body.
245
+ #
246
+ # <tt>raise Maveric::Response, 'Bad stuff'</tt> will generate a plain-text
247
+ # 500 response with the message as the body of the response.
248
+ #
249
+ # Additional or replacement responses should be set via Response#[]= and
250
+ # should be valid rack responses.
251
+ class Response < Exception
252
+ DEFAULT, @r = [500, 'text/plain'], {}
253
+ def self.[] e; @r[e]; end
254
+ def self.[]= e, v; @r[e]=v; end
255
+ def initialize err
256
+ resp = Response[err] || [ DEFAULT[0],
257
+ { 'Content-Type' => DEFAULT[1], 'Content-Length' => err.length.to_s },
258
+ err]
259
+ @status, @headers, @body = resp
260
+ super @body
261
+ end
262
+ def each; @body.each{|line| yield line }; end
263
+ def to_a; [@status, @headers, self]; end # to_splat in 1.9
264
+ alias_method :finish, :to_a
265
+ end
229
266
  end
230
267
 
268
+
269
+
231
270
  class Rack::Request
232
271
  # Allows the request to provide the current maveric.
233
272
  def maveric; @env['maveric']; end
234
- # Allows the request to provide the current session.
235
- def session; @env['rack.session']; end
236
- # Same as the standard Rack::Request method.
237
- def url; site_root + fullpath; end
238
273
  # Provides the compliment to #fullpath.
239
274
  def site_root
240
275
  url = scheme + "://" + host
@@ -243,8 +278,11 @@ class Rack::Request
243
278
  scheme == "http" && port != 80
244
279
  url
245
280
  end
281
+ def url; site_root + fullpath; end
246
282
  end
247
283
 
284
+
285
+
248
286
  Maveric::Response[401] = [401,
249
287
  {'Content-Type'=>'text/plain','Content-Length'=>'13'},
250
288
  ['Unauthorized.']]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scytrin-maveric
3
3
  version: !ruby/object:Gem::Version
4
- version: "2"
4
+ version: "3"
5
5
  platform: ruby
6
6
  authors:
7
7
  - scytrin