pakyow-core 0.8rc1 → 0.8.rc4

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