pakyow-core 0.8rc1 → 0.8.rc4

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 (51) hide show
  1. checksums.yaml +7 -0
  2. data/pakyow-core/lib/core/app.rb +448 -0
  3. data/pakyow-core/lib/core/base.rb +35 -12
  4. data/pakyow-core/lib/core/{configuration → config}/app.rb +38 -35
  5. data/pakyow-core/lib/core/config/base.rb +30 -0
  6. data/pakyow-core/lib/core/config/cookies.rb +21 -0
  7. data/pakyow-core/lib/core/config/logger.rb +37 -0
  8. data/pakyow-core/lib/core/{configuration → config}/server.rb +3 -1
  9. data/pakyow-core/lib/core/exceptions.rb +3 -0
  10. data/pakyow-core/lib/core/helpers.rb +20 -16
  11. data/pakyow-core/lib/core/loader.rb +1 -1
  12. data/pakyow-core/lib/core/middleware/logger.rb +170 -16
  13. data/pakyow-core/lib/core/middleware/static.rb +20 -8
  14. data/pakyow-core/lib/core/multilog.rb +19 -0
  15. data/pakyow-core/lib/core/request.rb +52 -30
  16. data/pakyow-core/lib/core/route_eval.rb +390 -0
  17. data/pakyow-core/lib/core/route_lookup.rb +17 -5
  18. data/pakyow-core/lib/core/route_set.rb +17 -210
  19. data/pakyow-core/lib/core/route_template_defaults.rb +18 -12
  20. data/pakyow-core/lib/core/router.rb +41 -31
  21. data/pakyow-core/lib/utils/dir.rb +19 -0
  22. data/pakyow-core/lib/utils/hash.rb +14 -4
  23. data/pakyow-core/lib/views/errors/404.html +77 -0
  24. data/pakyow-core/lib/views/errors/500.html +56 -0
  25. metadata +30 -53
  26. data/pakyow-core/bin/pakyow +0 -18
  27. data/pakyow-core/lib/commands/USAGE +0 -9
  28. data/pakyow-core/lib/commands/USAGE-CONSOLE +0 -12
  29. data/pakyow-core/lib/commands/USAGE-NEW +0 -11
  30. data/pakyow-core/lib/commands/USAGE-SERVER +0 -12
  31. data/pakyow-core/lib/commands/console.rb +0 -18
  32. data/pakyow-core/lib/commands/server.rb +0 -8
  33. data/pakyow-core/lib/core/application.rb +0 -330
  34. data/pakyow-core/lib/core/cache.rb +0 -25
  35. data/pakyow-core/lib/core/configuration/base.rb +0 -31
  36. data/pakyow-core/lib/core/fn_context.rb +0 -5
  37. data/pakyow-core/lib/core/log.rb +0 -39
  38. data/pakyow-core/lib/core/middleware/not_found.rb +0 -40
  39. data/pakyow-core/lib/core/middleware/presenter.rb +0 -25
  40. data/pakyow-core/lib/core/middleware/router.rb +0 -33
  41. data/pakyow-core/lib/core/middleware/setup.rb +0 -15
  42. data/pakyow-core/lib/core/presenter_base.rb +0 -11
  43. data/pakyow-core/lib/core/route_template.rb +0 -77
  44. data/pakyow-core/lib/generators/pakyow/app/app_generator.rb +0 -36
  45. data/pakyow-core/lib/generators/pakyow/app/templates/README +0 -54
  46. data/pakyow-core/lib/generators/pakyow/app/templates/app.rb +0 -12
  47. data/pakyow-core/lib/generators/pakyow/app/templates/config.ru +0 -3
  48. data/pakyow-core/lib/generators/pakyow/app/templates/public/favicon.ico +0 -0
  49. data/pakyow-core/lib/generators/pakyow/app/templates/rakefile +0 -2
  50. data/pakyow-core/lib/generators/pakyow/app/templates/views/main.html +0 -1
  51. data/pakyow-core/lib/generators/pakyow/app/templates/views/pakyow.html +0 -12
@@ -0,0 +1,390 @@
1
+ module Pakyow
2
+ class RouteEval
3
+ attr_reader :path
4
+
5
+ def initialize(path = '/', hooks = { :before => [], :after => []}, fns = {}, group_name = nil, namespace = false)
6
+ @path = path
7
+ @scope = {:path => path, :hooks => hooks, :group_name => group_name, :namespace => namespace}
8
+ @routes = {:get => [], :post => [], :put => [], :delete => []}
9
+ @lookup = {:routes => {}, :grouped => {}}
10
+ @fns = fns
11
+ @groups = {}
12
+ @templates = {}
13
+ @handlers = []
14
+
15
+ eval(&RouteTemplateDefaults.defaults)
16
+ end
17
+
18
+ def eval(template = false, &block)
19
+ # if we're evaling a template, need to push
20
+ # member routes to the end (they're always
21
+ # created first, but need to be the last out)
22
+ if template
23
+ @member_routes = @routes
24
+ @routes = {:get => [], :post => [], :put => [], :delete => []}
25
+ end
26
+
27
+ instance_exec(&block)
28
+
29
+ if template
30
+ merge_routes(@routes, @member_routes)
31
+ end
32
+ end
33
+
34
+ def merge(fns, routes, handlers, lookup)
35
+ # routes.merge!(@routes)
36
+ merge_routes(routes, @routes)
37
+ handlers.concat(@handlers)
38
+ # lookup.merge!(@lookup)
39
+ fns.merge!(@fns)
40
+
41
+ merge_lookup(lookup, @lookup)
42
+
43
+ return fns, routes, handlers, lookup
44
+ end
45
+
46
+ # Creates or retreives a named route function. When retrieving,
47
+ #
48
+ def fn(name, &block)
49
+ @fns[name] = block and return if block
50
+ @fns[name]
51
+ end
52
+
53
+ # def action(name, &block)
54
+ # @fns[name] = block and return if block
55
+ # @fns[name]
56
+ # end
57
+
58
+ def action(method, *args, &block)
59
+ fn, hooks = self.class.parse_action_args(args)
60
+ fns = block_given? ? [block] : [fn]
61
+ @fns[method] = build_fns(fns, hooks)
62
+ end
63
+
64
+ def default(*args, &block)
65
+ register_route(:get, '/', :default, *args, &block)
66
+ end
67
+
68
+ def get(*args, &block)
69
+ register_route(:get, *args, &block)
70
+ end
71
+
72
+ def put(*args, &block)
73
+ register_route(:put, *args, &block)
74
+ end
75
+
76
+ def post(*args, &block)
77
+ register_route(:post, *args, &block)
78
+ end
79
+
80
+ def delete(*args, &block)
81
+ register_route(:delete, *args, &block)
82
+ end
83
+
84
+ # Creates a handler.
85
+ #
86
+ def handler(*args, &block)
87
+ name, code, fns, hooks = self.class.parse_handler_args(args)
88
+ fns ||= []
89
+ # add passed block to fns
90
+ fns << block if block_given?
91
+
92
+ # build the final list of fns
93
+ fns = build_fns(fns, hooks)
94
+
95
+ @handlers << [name, code, fns]
96
+ end
97
+
98
+ def group(*args, &block)
99
+ name, hooks = self.class.parse_group_args(args)
100
+
101
+ evaluator = RouteEval.new(@scope[:path], merge_hooks(hooks, @scope[:hooks]), @fns, name)
102
+ evaluator.eval(&block)
103
+
104
+ @fns, @routes, @handlers, @lookup = evaluator.merge(@fns, @routes, @handlers, @lookup)
105
+ end
106
+
107
+ def namespace(*args, &block)
108
+ path, name, hooks = self.class.parse_namespace_args(args)
109
+
110
+ #TODO shouldn't this be in parse_namespace_args?
111
+ hooks = name if name.is_a?(Hash)
112
+
113
+ evaluator = RouteEval.new(File.join(@scope[:path], path), merge_hooks(hooks, @scope[:hooks]), @fns, name, true)
114
+ evaluator.eval(&block)
115
+
116
+ @fns, @routes, @handlers, @lookup = evaluator.merge(@fns, @routes, @handlers, @lookup)
117
+ end
118
+
119
+ def template(*args, &block)
120
+ name, hooks = self.class.parse_template_args(args)
121
+ @templates[name] = [hooks, block]
122
+ end
123
+
124
+ def expand(t_name, g_name, *args, &block)
125
+ path, hooks = self.class.parse_expansion_args(args)
126
+
127
+ template = @templates[t_name]
128
+
129
+ evaluator = RouteEval.new(File.join(@scope[:path], path), merge_hooks(merge_hooks(hooks, @scope[:hooks]), template[0]), @fns, g_name, true)
130
+ evaluator.eval(&block)
131
+ evaluator.eval(true, &template[1])
132
+
133
+ @fns, @routes, @handlers, @lookup = evaluator.merge(@fns, @routes, @handlers, @lookup)
134
+ end
135
+
136
+ protected
137
+
138
+ def merge_hooks(h1, h2)
139
+ # normalize
140
+ h1 = normalize_hooks(h1)
141
+ h2 = normalize_hooks(h2)
142
+
143
+ # merge
144
+ h1[:before].concat(h2[:before])
145
+ h1[:after].concat(h2[:after])
146
+ h1[:around].concat(h2[:around])
147
+
148
+ return h1
149
+ end
150
+
151
+ def merge_routes(r1, r2)
152
+ r1[:get].concat(r2[:get])
153
+ r1[:put].concat(r2[:put])
154
+ r1[:post].concat(r2[:post])
155
+ r1[:delete].concat(r2[:delete])
156
+
157
+ return r1
158
+ end
159
+
160
+ def merge_lookup(l1, l2)
161
+ l1[:routes].merge!(l2[:routes])
162
+ l1[:grouped].merge!(l2[:grouped])
163
+
164
+ return l1
165
+ end
166
+
167
+ def copy_hooks(hooks)
168
+ {
169
+ :before => (hooks[:before] || []).dup,
170
+ :after => (hooks[:after] || []).dup,
171
+ :around => (hooks[:around] || []).dup,
172
+ }
173
+ end
174
+
175
+ def register_route(method, *args, &block)
176
+ path, name, fns, hooks = self.class.parse_route_args(args)
177
+
178
+ fns ||= []
179
+ # add passed block to fns
180
+ fns << block if block_given?
181
+
182
+ # merge route hooks with scoped hooks
183
+ hooks = merge_hooks(hooks || {}, @scope[:hooks])
184
+
185
+ # build the final list of fns
186
+ fns = build_fns(fns, hooks)
187
+
188
+ if path.is_a?(Regexp)
189
+ regex = path
190
+ vars = []
191
+ else
192
+ # prepend scope path if we're in a scope
193
+ path = File.join(@scope[:path], path)
194
+ path = StringUtils.normalize_path(path)
195
+
196
+ # get regex and vars for path
197
+ regex, vars = build_route_matcher(path)
198
+ end
199
+
200
+ # create the route tuple
201
+ route = [regex, vars, name, fns, path]
202
+
203
+ @routes[method] << route
204
+
205
+ # add route to lookup, unless it's namespaced (because
206
+ # then it can only be accessed through the grouping)
207
+ unless namespace?
208
+ @lookup[:routes][name] = route
209
+ end
210
+
211
+ # add to grouped lookup, if we're in a group
212
+ if group?
213
+ (@lookup[:grouped][@scope[:group_name]] ||= {})[name] = route
214
+ end
215
+ end
216
+
217
+ def build_route_matcher(path)
218
+ return path, [] if path.is_a?(Regexp)
219
+
220
+ # check for vars
221
+ return path, [] unless path[0,1] == ':' || path.index('/:')
222
+
223
+ # we have vars
224
+ vars = []
225
+ regex_route = path
226
+ route_segments = path.split('/')
227
+ route_segments.each_with_index { |segment, i|
228
+ if segment.include?(':')
229
+ var = segment.gsub(':', '')
230
+ vars << { :var => var.to_sym, :url_position => i }
231
+ regex_route = regex_route.sub(segment, '(?<' + var + '>(\w|[-.~:@!$\'\(\)\*\+,;])*)')
232
+ end
233
+ }
234
+ reg = Regexp.new("^#{regex_route}$")
235
+ return reg, vars
236
+ end
237
+
238
+ def group?
239
+ !@scope[:group_name].nil?
240
+ end
241
+
242
+ def namespace?
243
+ @scope[:namespace]
244
+ end
245
+
246
+ # yields current path to the block for modification,
247
+ # then updates paths for member routes
248
+ def nested_path
249
+ new_path = yield(@scope[:group_name], @path)
250
+
251
+ # update paths of member routes
252
+ @member_routes.each {|type,routes|
253
+ routes.each { |route|
254
+ path = StringUtils.normalize_path(File.join(new_path, route[4].gsub(/^#{StringUtils.normalize_path(@path)}/, '')))
255
+ regex, vars = build_route_matcher(path)
256
+ route[0] = regex
257
+ route[1] = vars
258
+ route[4] = path
259
+ }
260
+ }
261
+
262
+ @path = new_path
263
+ end
264
+
265
+ def build_fns(main_fns, hooks)
266
+ hooks = normalize_hooks(hooks)
267
+ fns = []
268
+ fns.concat(hooks[:around]) if hooks && hooks[:around]
269
+ fns.concat(hooks[:before]) if hooks && hooks[:before]
270
+ fns.concat(main_fns) if main_fns
271
+ fns.concat(hooks[:after]) if hooks && hooks[:after]
272
+ fns.concat(hooks[:around]) if hooks && hooks[:around]
273
+ fns
274
+ end
275
+
276
+ def normalize_hooks(hooks)
277
+ hooks ||= {}
278
+
279
+ [:before, :after, :around].each do |type|
280
+ # force array
281
+ hooks[type] = Array(hooks[type])
282
+
283
+ # lookup hook fns if not already a Proc
284
+ hooks[type] = hooks[type].map do |hook|
285
+ hook.is_a?(Symbol) ? fn(hook) : hook
286
+ end
287
+ end
288
+
289
+ return hooks
290
+ end
291
+
292
+ class << self
293
+ def parse_route_args(args)
294
+ ret = []
295
+ args.each { |arg|
296
+ if arg.is_a?(Hash) # we have hooks
297
+ ret[3] = arg
298
+ elsif arg.is_a?(Array) # we have fns
299
+ ret[2] = arg
300
+ elsif arg.is_a?(Proc) # we have a fn
301
+ ret[2] = [arg]
302
+ elsif arg.is_a?(Symbol) # we have a name
303
+ ret[1] = arg
304
+ elsif !arg.nil? # we have a path
305
+ ret[0] = arg
306
+ end
307
+ }
308
+ ret
309
+ end
310
+
311
+ def parse_namespace_args(args)
312
+ ret = []
313
+ args.each { |arg|
314
+ if arg.is_a?(Hash) # we have hooks
315
+ ret[2] = arg
316
+ elsif arg.is_a?(Symbol) # we have a name
317
+ ret[1] = arg
318
+ elsif !arg.nil? # we have a path
319
+ ret[0] = arg
320
+ end
321
+ }
322
+ ret
323
+ end
324
+
325
+ def parse_group_args(args)
326
+ ret = []
327
+ args.each { |arg|
328
+ if arg.is_a?(Hash) # we have hooks
329
+ ret[1] = arg
330
+ elsif !arg.nil? # we have a name
331
+ ret[0] = arg
332
+ end
333
+ }
334
+ ret
335
+ end
336
+
337
+ def parse_handler_args(args)
338
+ ret = []
339
+ args.each { |arg|
340
+ if arg.is_a?(Hash) # we have hooks
341
+ ret[3] = arg
342
+ elsif arg.is_a?(Proc) # we have a fn
343
+ ret[2] = [arg]
344
+ elsif arg.is_a?(Integer) # we have a code
345
+ ret[1] = arg
346
+ elsif !arg.nil? # we have a name
347
+ ret[0] = arg
348
+ end
349
+ }
350
+ ret
351
+ end
352
+
353
+ def parse_template_args(args)
354
+ ret = []
355
+ args.each { |arg|
356
+ if arg.is_a?(Hash) # we have hooks
357
+ ret[1] = arg
358
+ elsif !arg.nil? # we have a name
359
+ ret[0] = arg
360
+ end
361
+ }
362
+ ret
363
+ end
364
+
365
+ def parse_expansion_args(args)
366
+ ret = []
367
+ args.each { |arg|
368
+ if arg.is_a?(Hash) # we have hooks
369
+ ret[1] = arg
370
+ elsif !arg.nil? # we have a path
371
+ ret[0] = arg
372
+ end
373
+ }
374
+ ret
375
+ end
376
+
377
+ def parse_action_args(args)
378
+ ret = []
379
+ args.each { |arg|
380
+ if arg.is_a?(Hash) # we have hooks
381
+ ret[1] = arg
382
+ elsif arg.is_a?(Proc) # we have a fn
383
+ ret[0] = arg
384
+ end
385
+ }
386
+ ret
387
+ end
388
+ end
389
+ end
390
+ end
@@ -7,8 +7,9 @@ module Pakyow
7
7
  include Helpers
8
8
 
9
9
  def path(name, data = nil)
10
- route = self.get_named_route(name)
11
- data ? self.populate(route, data) : File.join('/', route[4])
10
+ if route = get_named_route(name)
11
+ data ? populate(route, data) : File.join('/', route[4])
12
+ end
12
13
  end
13
14
 
14
15
  def group(name)
@@ -19,7 +20,11 @@ module Pakyow
19
20
  protected
20
21
 
21
22
  def get_named_route(name)
22
- Pakyow.app.router.route(name, @group) || []
23
+ if defined? @group
24
+ Router.instance.route(name, @group)
25
+ else
26
+ Router.instance.route(name)
27
+ end
23
28
  end
24
29
 
25
30
  def populate(route, data = {})
@@ -28,10 +33,17 @@ module Pakyow
28
33
  split_path = Request.split_url(route[4])
29
34
 
30
35
  vars.each {|v|
31
- split_path[v[:position]] = data[v[:var]]
36
+ split_path[v[:url_position]] = data.delete(v[:var])
32
37
  }
33
38
 
34
- File.join('/', split_path.join('/'))
39
+ populated = File.join('/', split_path.join('/'))
40
+
41
+ # add remaining data to query string
42
+ unless data.empty?
43
+ populated << '/?' + data.map { |k,v| "#{k}=#{v}" }.join('&')
44
+ end
45
+
46
+ return populated
35
47
  end
36
48
  end
37
49
  end
@@ -1,118 +1,19 @@
1
1
  module Pakyow
2
2
  class RouteSet
3
+ attr_reader :routes, :lookup
4
+
3
5
  def initialize
4
6
  @routes = {:get => [], :post => [], :put => [], :delete => []}
5
-
6
- @routes_by_name = {}
7
- @grouped_routes_by_name = {}
8
-
9
- @fns = {}
10
- @groups = {}
11
-
12
- @templates = {}
13
-
7
+ @lookup = { :routes => {}, :grouped => {}}
14
8
  @handlers = []
15
-
16
- @scope = {:name => nil, :path => '/', :hooks => {:before => [], :after => []}}
17
- end
18
-
19
- # Creates or retreives a named route function. When retrieving,
20
- #
21
- def fn(name, &block)
22
- @fns[name] = block and return if block
23
-
24
- #TODO rewrite to not return array
25
- [@fns[name]]
26
- end
27
-
28
- def default(*args, &block)
29
- self.register_route(:get, '/', *args, &block)
30
- end
31
-
32
- def get(*args, &block)
33
- self.register_route(:get, *args, &block)
34
- end
35
-
36
- def put(*args, &block)
37
- self.register_route(:put, *args, &block)
38
- end
39
-
40
- def post(*args, &block)
41
- self.register_route(:post, *args, &block)
42
- end
43
-
44
- def delete(*args, &block)
45
- self.register_route(:delete, *args, &block)
46
- end
47
-
48
- # Returns a lambda that routes request to a controller/action.
49
- #TODO move to RouteHelpers
50
- def call(controller, action)
51
- lambda {
52
- controller = Object.const_get(controller)
53
- action ||= Configuration::Base.app.default_action
54
-
55
- instance = controller.new
56
- request.controller = instance
57
- request.action = action
58
-
59
- instance.send(action)
60
- }
61
- end
62
-
63
- # Creates a handler.
64
- #
65
- def handler(name, *args, &block)
66
- code, fn = args
67
-
68
- fn = code and code = nil if code.is_a?(Proc)
69
- fn = block if block_given?
70
-
71
- @handlers << [name, code, [fn]]
72
- end
73
-
74
- def group(name, *args, &block)
75
- # deep clone existing hooks to reset at the close of this group
76
- original_hooks = Marshal.load(Marshal.dump(@scope[:hooks]))
77
-
78
- @scope[:hooks] = self.merge_hooks(@scope[:hooks], args[0]) if @scope[:hooks] && args[0]
79
-
80
- @scope[:name] = name
81
- @groups[name] = []
82
- @grouped_routes_by_name[name] = {}
83
-
84
- self.instance_exec(&block)
85
- @scope[:name] = nil
86
-
87
- @scope[:hooks] = original_hooks
9
+ @fns = {}
88
10
  end
89
11
 
90
- def namespace(path, *args, &block)
91
- name, hooks = args
92
- hooks = name if name.is_a?(Hash)
93
-
94
- original_path = @scope[:path]
95
- @scope[:path] = File.join(@scope[:path], path)
96
-
97
- self.group(name, hooks || {}, &block)
98
- @scope[:path] = original_path
99
- end
12
+ def eval(&block)
13
+ evaluator = RouteEval.new
14
+ evaluator.eval(&block)
100
15
 
101
- def template(name, &block)
102
- @templates[name] = block
103
- end
104
-
105
- def expand(t_name, g_name, path = nil, data = nil, &block)
106
- data = path and path = nil if path.is_a?(Hash)
107
-
108
- # evaluate block in context of some class that implements
109
- # method_missing to store map of functions
110
- # (e.g. index, show)
111
- t = RouteTemplate.new(block, g_name, path, self)
112
-
113
- # evaluate template in same context, where func looks up funcs
114
- # from map and extends get (and others) to add proper names
115
- t.expand(@templates[t_name], data)
16
+ @fns, @routes, @handlers, @lookup = evaluator.merge(@fns, @routes, @handlers, @lookup)
116
17
  end
117
18
 
118
19
  # Returns a route tuple:
@@ -121,7 +22,7 @@ module Pakyow
121
22
  def match(path, method)
122
23
  path = StringUtils.normalize_path(path)
123
24
 
124
- @routes[method.to_sym].each{|r|
25
+ @routes[method.to_sym].each{|r|
125
26
  case r[0]
126
27
  when Regexp
127
28
  if data = r[0].match(path)
@@ -147,113 +48,19 @@ module Pakyow
147
48
 
148
49
  # Name based route lookup
149
50
  def route(name, group = nil)
150
- return @routes_by_name[name] unless group
51
+ return @lookup[:routes][name] if group.nil?
151
52
 
152
- if grouped_routes = @grouped_routes_by_name[group]
153
- grouped_routes[name]
53
+ if grouped_routes = @lookup[:grouped][group]
54
+ return grouped_routes[name]
55
+ else
56
+ #TODO error
154
57
  end
155
58
  end
156
59
 
157
- protected
158
-
159
- def merge_hooks(h1, h2)
160
- # normalize
161
- h1[:before] ||= []
162
- h1[:after] ||= []
163
- h1[:around] ||= []
164
- h2[:before] ||= []
165
- h2[:after] ||= []
166
- h2[:around] ||= []
167
-
168
- # merge
169
- h1[:before].concat(h2[:before])
170
- h1[:after].concat(h2[:after])
171
- h1[:around].concat(h2[:around])
172
- h1
173
- end
174
-
175
- def register_route(method, path, *args, &block)
176
- name, fns, hooks = self.parse_route_args(args)
177
-
178
- fns ||= []
179
- # add passed block to fns
180
- fns << block if block_given?
181
-
182
- hooks = self.merge_hooks(hooks || {}, @scope[:hooks])
183
-
184
- # build the final list of fns
185
- fns = self.build_fns(fns, hooks)
186
-
187
- # prepend scope path if we're in a scope
188
- path = File.join(@scope[:path], path)
189
- path = StringUtils.normalize_path(path)
190
-
191
- # get regex and vars for path
192
- regex, vars = self.build_route_matcher(path)
193
-
194
- # create the route tuple
195
- route = [regex, vars, name, fns, path]
196
-
197
- @routes[method] << route
198
- @routes_by_name[name] = route
199
-
200
- # store group references if we're in a scope
201
- return unless group = @scope[:name]
202
- @groups[group] << route
203
- @grouped_routes_by_name[group][name] = route
204
- end
205
-
206
- def parse_route_args(args)
207
- ret = []
208
- args.each { |arg|
209
- if arg.is_a?(Hash) # we have hooks
210
- ret[2] = arg
211
- elsif arg.is_a?(Array) # we have fns
212
- ret[1] = arg
213
- elsif arg.is_a?(Proc) # we have a fn
214
- ret[1] = [arg]
215
- elsif !arg.nil? # we have a name
216
- ret[0] = arg
217
- end
218
- }
219
- ret
220
- end
221
-
222
- def build_fns(main_fns, hooks)
223
- fns = []
224
- fns.concat(hooks[:around]) if hooks && hooks[:around]
225
- fns.concat(hooks[:before]) if hooks && hooks[:before]
226
- fns.concat(main_fns) if main_fns
227
- fns.concat(hooks[:after]) if hooks && hooks[:after]
228
- fns.concat(hooks[:around]) if hooks && hooks[:around]
229
- fns
230
- end
231
-
232
- def build_route_matcher(path)
233
- return path, [] if path.is_a?(Regexp)
234
60
 
235
- # check for vars
236
- return path, [] unless path[0,1] == ':' || path.index('/:')
237
-
238
- # we have vars
239
- vars = []
240
- position_counter = 1
241
- regex_route = path
242
- route_segments = path.split('/')
243
- route_segments.each_with_index { |segment, i|
244
- if segment.include?(':')
245
- vars << { :position => position_counter, :var => segment.gsub(':', '').to_sym }
246
- if i == route_segments.length-1 then
247
- regex_route = regex_route.sub(segment, '((\w|[-.~:@!$\'\(\)\*\+,;])*)')
248
- position_counter += 2
249
- else
250
- regex_route = regex_route.sub(segment, '((\w|[-.~:@!$\'\(\)\*\+,;])*)')
251
- position_counter += 2
252
- end
253
- end
254
- }
255
- reg = Regexp.new("^#{regex_route}$")
256
- return reg, vars
61
+ # Name based fn lookup
62
+ def fn(name)
63
+ return @fns[name]
257
64
  end
258
65
  end
259
66
  end