pakyow-core 0.9.1 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -17,23 +17,24 @@ module Pakyow
17
17
  return instance
18
18
  end
19
19
 
20
- def from_scope(route_eval, overrides = {})
21
- args = [:path, :fns, :hooks, :templates, :group].inject([]) do |acc, arg|
22
- acc << (overrides.fetch(arg) { route_eval.send(arg) })
20
+ def from_scope(route_eval, args = {})
21
+ [:path, :fns, :hooks, :templates, :group].each do |arg|
22
+ next unless value = route_eval.instance_variable_get(:"@#{arg}")
23
+ args[arg] ||= value.dup
23
24
  end
24
25
 
25
- instance = self.new(*args)
26
+ self.new(args)
26
27
  end
27
28
  end
28
29
 
29
- def initialize(path = '/', fns = nil, hooks = nil, templates = nil, group = nil)
30
+ def initialize(path: '/', fns: {}, hooks: { before: [], after: [] }, templates: {}, group: nil)
30
31
  @path = path
31
- @fns = fns || {}
32
- @routes = HTTP_METHODS.inject({}) { |acc, m| acc[m] = []; acc }
33
- @hooks = hooks || { before: [], after: [] }
34
- @templates = templates || {}
32
+ @fns = fns
33
+ @hooks = hooks
34
+ @templates = templates
35
35
  @group = group
36
36
 
37
+ @routes = HTTP_METHODS.inject({}) { |acc, m| acc[m] = []; acc }
37
38
  @lookup = { routes: {}, grouped: {} }
38
39
  @handlers = []
39
40
  end
@@ -52,7 +53,7 @@ module Pakyow
52
53
  instance_exec(&block)
53
54
  end
54
55
 
55
- # Creates or retreives a named route function. When retrieving,
56
+ # Creates or retreives a named route function.
56
57
  #
57
58
  def fn(name, &block)
58
59
  if block_given?
@@ -65,15 +66,18 @@ module Pakyow
65
66
  # Creates a handler.
66
67
  #
67
68
  def handler(*args, &block)
68
- name, code, fns, hooks = self.class.parse_handler_args(args)
69
- fns ||= []
69
+ args = Aargv.normalize(args, name: Symbol, code: Integer, fn: Proc, hooks: Hash)
70
+
71
+ fns = []
72
+ # add the passed proc
73
+ fns << args[:fn] unless args[:fn].nil?
70
74
  # add passed block to fns
71
75
  fns << block if block_given?
72
76
 
73
77
  # build the final list of fns
74
- fns = build_fns(fns, hooks)
78
+ fns = build_fns(fns, args[:hooks])
75
79
 
76
- @handlers.unshift([name, code, fns])
80
+ @handlers.unshift([args[:name], args[:code], fns])
77
81
  end
78
82
 
79
83
  def group(*args, &block)
@@ -95,22 +99,21 @@ module Pakyow
95
99
  end
96
100
 
97
101
  def template(*args, &block)
98
- name, hooks = self.class.parse_template_args(args)
99
-
100
- @templates[name] = [hooks, block]
102
+ args = Aargv.normalize(args, name: Symbol, hooks: Hash)
103
+ @templates[args[:name]] = [args[:hooks], block]
101
104
  end
102
105
 
103
106
  def expand(t_name, g_name = nil, *args, &block)
104
- path, hooks = self.class.parse_expansion_args(args)
105
- path ||= ''
106
-
107
+ args = Aargv.normalize(args, path: [String, ''], hooks: Hash)
108
+ path = args[:path]
109
+ hooks = args[:hooks]
107
110
  template = @templates[t_name]
108
111
 
109
112
  evaluator = RouteExpansionEval.from_scope(self, path: File.join(descendent_path, path), group: g_name, hooks: hooks)
110
113
  evaluator.direct_path = path
111
114
  evaluator.set_template(g_name, template)
112
115
  evaluator.eval(&block)
113
-
116
+
114
117
  merge(evaluator)
115
118
  end
116
119
 
@@ -130,7 +133,6 @@ module Pakyow
130
133
  expand(method, *args, &block)
131
134
  else
132
135
  super
133
- # action(method, *args, &block)
134
136
  end
135
137
  end
136
138
 
@@ -141,14 +143,19 @@ module Pakyow
141
143
  protected
142
144
 
143
145
  def build_route(method, *args, &block)
144
- path, name, fns, hooks = self.class.parse_route_args(args)
145
-
146
- fns ||= []
146
+ args = Aargv.normalize(args, path: String, regex_path: Regexp, name: Symbol, fn: Proc, fns: Array, hooks: Hash)
147
+
148
+ path = args[:path] || args[:regex_path]
149
+ name = args[:name]
150
+
151
+ fns = args[:fns] || []
152
+ # add passed fn
153
+ fns << args[:fn] unless args[:fn].nil?
147
154
  # add passed block to fns
148
155
  fns << block if block_given?
149
156
 
150
157
  # merge route hooks with scoped hooks
151
- hooks = merge_hooks(hooks || {}, @hooks)
158
+ hooks = merge_hooks(@hooks, args[:hooks] || {})
152
159
 
153
160
  # build the final list of fns
154
161
  fns = build_fns(fns, hooks)
@@ -217,24 +224,6 @@ module Pakyow
217
224
  end
218
225
 
219
226
  class << self
220
- def parse_route_args(args)
221
- ret = []
222
- args.each { |arg|
223
- if arg.is_a?(Hash) # we have hooks
224
- ret[3] = arg
225
- elsif arg.is_a?(Array) # we have fns
226
- ret[2] = arg
227
- elsif arg.is_a?(Proc) # we have a fn
228
- ret[2] = [arg]
229
- elsif arg.is_a?(Symbol) # we have a name
230
- ret[1] = arg
231
- elsif !arg.nil? # we have a path
232
- ret[0] = arg
233
- end
234
- }
235
- ret
236
- end
237
-
238
227
  def parse_namespace_args(args)
239
228
  ret = []
240
229
  args.each { |arg|
@@ -260,225 +249,6 @@ module Pakyow
260
249
  }
261
250
  ret
262
251
  end
263
-
264
- def parse_handler_args(args)
265
- ret = []
266
- args.each { |arg|
267
- if arg.is_a?(Hash) # we have hooks
268
- ret[3] = arg
269
- elsif arg.is_a?(Proc) # we have a fn
270
- ret[2] = [arg]
271
- elsif arg.is_a?(Integer) # we have a code
272
- ret[1] = arg
273
- elsif !arg.nil? # we have a name
274
- ret[0] = arg
275
- end
276
- }
277
- ret
278
- end
279
-
280
- def parse_template_args(args)
281
- ret = []
282
- args.each { |arg|
283
- if arg.is_a?(Hash) # we have hooks
284
- ret[1] = arg
285
- elsif !arg.nil? # we have a name
286
- ret[0] = arg
287
- end
288
- }
289
- ret
290
- end
291
-
292
- def parse_expansion_args(args)
293
- ret = []
294
- args.each { |arg|
295
- if arg.is_a?(Hash) # we have hooks
296
- ret[1] = arg
297
- elsif !arg.nil? # we have a path
298
- ret[0] = arg
299
- end
300
- }
301
- ret
302
- end
303
252
  end
304
253
  end
305
-
306
- class RouteExpansionEval < RouteEval
307
- attr_writer :direct_path
308
-
309
- def eval(&block)
310
- @template_eval = RouteTemplateEval.from_scope(self, path: path, group: @group, hooks: @hooks)
311
- @template_eval.direct_path = @direct_path
312
- @template_eval.eval(&@template_block)
313
-
314
- @path = @template_eval.routes_path
315
-
316
- super
317
- end
318
-
319
- def set_template(expansion_name, template)
320
- @expansion_name = expansion_name
321
- @template_block = template[1]
322
-
323
- @hooks = merge_hooks(@hooks, template[0])
324
- end
325
-
326
- def action(method, *args, &block)
327
- fn, hooks = self.class.parse_action_args(args)
328
- fn = block if block_given?
329
-
330
- # get route info from template
331
- route = @template_eval.route_for_action(method)
332
-
333
- all_fns = route[3]
334
- all_fns[:fns].unshift(fn) if fn
335
-
336
- hooks = merge_hooks(hooks, all_fns[:hooks])
337
- route[3] = build_fns(all_fns[:fns], hooks)
338
-
339
- register_route(route)
340
- end
341
-
342
- def action_group(*args, &block)
343
- name, hooks = self.class.parse_action_group_args(args)
344
- group = @template_eval.group_named(name)
345
-
346
- hooks = merge_hooks(hooks, group[0])
347
- group(@expansion_name, hooks, &block)
348
- end
349
-
350
- def action_namespace(*args, &block)
351
- name, hooks = self.class.parse_action_namespace_args(args)
352
- namespace = @template_eval.namespace_named(name)
353
-
354
- hooks = merge_hooks(hooks, namespace[1])
355
- namespace(@expansion_name, namespace[0], hooks, &block)
356
- end
357
-
358
- def method_missing(method, *args, &block)
359
- if @template_eval.has_action?(method)
360
- action(method, *args, &block)
361
- elsif @template_eval.has_namespace?(method)
362
- action_namespace(method, *args, &block)
363
- elsif @template_eval.has_group?(method)
364
- action_group(method, *args, &block)
365
- else
366
- super
367
- end
368
- rescue NoMethodError
369
- raise UnknownTemplatePart, "No action, namespace, or group named '#{method}'"
370
- end
371
-
372
- def expand(*args, &block)
373
- args[2] = File.join(@template_eval.nested_path.gsub(@path, ''), args[2])
374
- super(*args, &block)
375
- end
376
-
377
- private
378
-
379
- class << self
380
- def parse_action_args(args)
381
- ret = []
382
- args.each { |arg|
383
- if arg.is_a?(Hash) # we have hooks
384
- ret[1] = arg
385
- elsif arg.is_a?(Proc) # we have a fn
386
- ret[0] = arg
387
- end
388
- }
389
- ret
390
- end
391
-
392
- def parse_action_namespace_args(args)
393
- ret = []
394
- args.each { |arg|
395
- if arg.is_a?(Hash) # we have hooks
396
- ret[1] = arg
397
- elsif arg.is_a?(Symbol) # we have a name
398
- ret[0] = arg
399
- end
400
- }
401
- ret
402
- end
403
-
404
- def parse_action_group_args(args)
405
- ret = []
406
- args.each { |arg|
407
- if arg.is_a?(Hash) # we have hooks
408
- ret[1] = arg
409
- elsif !arg.nil? # we have a name
410
- ret[0] = arg
411
- end
412
- }
413
- ret
414
- end
415
- end
416
- end
417
-
418
- class RouteTemplateEval < RouteEval
419
- attr_accessor :direct_path
420
-
421
- def initialize(*args)
422
- super
423
-
424
- @groups = {}
425
- @namespaces = {}
426
-
427
- @routes_path = path
428
- @nested_path = path
429
- end
430
-
431
- def has_action?(name)
432
- !route_for_action(name).nil?
433
- end
434
-
435
- def has_group?(name)
436
- !group_named(name).nil?
437
- end
438
-
439
- def has_namespace?(name)
440
- !namespace_named(name).nil?
441
- end
442
-
443
- def route_for_action(name)
444
- lookup.fetch(:grouped, {}).fetch(@group, {})[name]
445
- end
446
-
447
- def namespace_named(name)
448
- @namespaces[name]
449
- end
450
-
451
- def group_named(name)
452
- @groups[name]
453
- end
454
-
455
- def build_fns(fns, hooks)
456
- {
457
- fns: fns,
458
- hooks: hooks,
459
- }
460
- end
461
-
462
- def namespace(*args)
463
- path, name, hooks = self.class.parse_namespace_args(args)
464
- @namespaces[name] = [path, hooks]
465
- end
466
-
467
- def group(*args)
468
- name, hooks = self.class.parse_group_args(args)
469
- @groups[name] = [hooks]
470
- end
471
-
472
- def routes_path(&block)
473
- return @routes_path unless block_given?
474
- @routes_path = yield(@routes_path)
475
- @path = @routes_path
476
- end
477
-
478
- def nested_path(&block)
479
- return @nested_path unless block_given?
480
- @nested_path = yield(@nested_path)
481
- end
482
- end
483
254
  end
484
-
@@ -0,0 +1,115 @@
1
+ module Pakyow
2
+ class RouteExpansionEval < RouteEval
3
+ attr_writer :direct_path
4
+
5
+ def eval(&block)
6
+ @template_eval = RouteTemplateEval.from_scope(self, path: path, group: @group, hooks: @hooks)
7
+ @template_eval.direct_path = @direct_path
8
+ @template_eval.eval(&@template_block)
9
+
10
+ @path = @template_eval.routes_path
11
+
12
+ super
13
+
14
+ instance_exec(&@template_eval.post_process) if @template_eval.post_process
15
+ end
16
+
17
+ def set_template(expansion_name, template)
18
+ @expansion_name = expansion_name
19
+ @template_block = template[1]
20
+
21
+ @hooks = merge_hooks(@hooks, template[0])
22
+ end
23
+
24
+ def action(method, *args, &block)
25
+ fn, hooks = self.class.parse_action_args(args)
26
+ fn = block if block_given?
27
+
28
+ # get route info from template
29
+ route = @template_eval.route_for_action(method)
30
+
31
+ all_fns = route[3]
32
+ all_fns[:fns].unshift(fn) if fn
33
+
34
+ hooks = merge_hooks(hooks, all_fns[:hooks])
35
+ route[3] = build_fns(all_fns[:fns], hooks)
36
+
37
+ register_route(route)
38
+ end
39
+
40
+ def action_group(*args, &block)
41
+ name, hooks = self.class.parse_action_group_args(args)
42
+ group = @template_eval.group_named(name)
43
+
44
+ hooks = merge_hooks(hooks, group[0])
45
+ group(@expansion_name, hooks, &block)
46
+ end
47
+
48
+ def action_namespace(*args, &block)
49
+ name, hooks = self.class.parse_action_namespace_args(args)
50
+ namespace = @template_eval.namespace_named(name)
51
+
52
+ hooks = merge_hooks(hooks, namespace[1])
53
+ namespace(@expansion_name, namespace[0], hooks, &block)
54
+ end
55
+
56
+ def method_missing(method, *args, &block)
57
+ if @template_eval.has_action?(method)
58
+ action(method, *args, &block)
59
+ elsif @template_eval.has_namespace?(method)
60
+ action_namespace(method, *args, &block)
61
+ elsif @template_eval.has_group?(method)
62
+ action_group(method, *args, &block)
63
+ else
64
+ super
65
+ end
66
+ rescue NoMethodError
67
+ raise UnknownTemplatePart, "No action, namespace, or group named '#{method}'"
68
+ end
69
+
70
+ def expand(*args, &block)
71
+ args[2] = File.join(@template_eval.nested_path.gsub(@path, ''), args[2])
72
+ super(*args, &block)
73
+ end
74
+
75
+ private
76
+
77
+ class << self
78
+ def parse_action_args(args)
79
+ ret = []
80
+ args.each { |arg|
81
+ if arg.is_a?(Hash) # we have hooks
82
+ ret[1] = arg
83
+ elsif arg.is_a?(Proc) # we have a fn
84
+ ret[0] = arg
85
+ end
86
+ }
87
+ ret
88
+ end
89
+
90
+ def parse_action_namespace_args(args)
91
+ ret = []
92
+ args.each { |arg|
93
+ if arg.is_a?(Hash) # we have hooks
94
+ ret[1] = arg
95
+ elsif arg.is_a?(Symbol) # we have a name
96
+ ret[0] = arg
97
+ end
98
+ }
99
+ ret
100
+ end
101
+
102
+ def parse_action_group_args(args)
103
+ ret = []
104
+ args.each { |arg|
105
+ if arg.is_a?(Hash) # we have hooks
106
+ ret[1] = arg
107
+ elsif !arg.nil? # we have a name
108
+ ret[0] = arg
109
+ end
110
+ }
111
+ ret
112
+ end
113
+ end
114
+ end
115
+ end
@@ -35,14 +35,7 @@ module Pakyow
35
35
  split_path[v[:url_position]] = data.delete(v[:var])
36
36
  }
37
37
 
38
- populated = File.join('/', split_path.join('/'))
39
-
40
- # add remaining data to query string
41
- unless data.empty?
42
- populated << '/?' + data.map { |k,v| "#{k}=#{v}" }.join('&')
43
- end
44
-
45
- return populated
38
+ File.join('/', split_path.join('/'))
46
39
  end
47
40
  end
48
41
  end
@@ -7,10 +7,13 @@ module Pakyow
7
7
  resource_id = ":#{@group}_id"
8
8
 
9
9
  nested_path { |path| File.join(path, resource_id) }
10
- view_path = direct_path.gsub(/:[^\/]+/, '').split('/').reject { |p| p.empty? }.join('/')
10
+ view_path = nested_path.gsub(/:[^\/]+/, '').split('/').reject { |p| p.empty? }.join('/')
11
11
 
12
12
  fn :reset_view_path do
13
- presenter.path = File.join(view_path, 'show') if @presenter
13
+ begin
14
+ presenter.path = File.join(view_path, 'show') if @presenter
15
+ rescue Presenter::MissingView
16
+ end
14
17
  end
15
18
 
16
19
  get :list, '/'
@@ -26,6 +29,13 @@ module Pakyow
26
29
 
27
30
  group :collection
28
31
  namespace :member, resource_id
32
+
33
+ post_process do
34
+ # the show route is weird; move it to the end of get routes to avoid conflicts
35
+ if show_index = @routes[:get].find_index { |route| route[2] == :show }
36
+ @routes[:get] << @routes[:get].delete_at(show_index)
37
+ end
38
+ end
29
39
  end
30
40
 
31
41
  end
@@ -0,0 +1,72 @@
1
+ module Pakyow
2
+ class RouteTemplateEval < RouteEval
3
+ attr_accessor :direct_path
4
+
5
+ def initialize(*args)
6
+ super
7
+
8
+ @groups = {}
9
+ @namespaces = {}
10
+
11
+ @routes_path = path
12
+ @nested_path = path
13
+ end
14
+
15
+ def has_action?(name)
16
+ !route_for_action(name).nil?
17
+ end
18
+
19
+ def has_group?(name)
20
+ !group_named(name).nil?
21
+ end
22
+
23
+ def has_namespace?(name)
24
+ !namespace_named(name).nil?
25
+ end
26
+
27
+ def route_for_action(name)
28
+ lookup.fetch(:grouped, {}).fetch(@group, {})[name]
29
+ end
30
+
31
+ def namespace_named(name)
32
+ @namespaces[name]
33
+ end
34
+
35
+ def group_named(name)
36
+ @groups[name]
37
+ end
38
+
39
+ def build_fns(fns, hooks)
40
+ {
41
+ fns: fns,
42
+ hooks: hooks,
43
+ }
44
+ end
45
+
46
+ def namespace(*args)
47
+ path, name, hooks = self.class.parse_namespace_args(args)
48
+ @namespaces[name] = [path, hooks]
49
+ end
50
+
51
+ def group(*args)
52
+ name, hooks = self.class.parse_group_args(args)
53
+ @groups[name] = [hooks]
54
+ end
55
+
56
+ def routes_path(&block)
57
+ return @routes_path unless block_given?
58
+ @routes_path = yield(@routes_path)
59
+ @path = @routes_path
60
+ end
61
+
62
+ def nested_path(&block)
63
+ return @nested_path unless block_given?
64
+ @nested_path = yield(@nested_path)
65
+ end
66
+
67
+ def post_process(&block)
68
+ return @post_process unless block_given?
69
+ @post_process = block
70
+ end
71
+ end
72
+ end
@@ -68,8 +68,14 @@ module Pakyow
68
68
 
69
69
  # Looks up and populates a path with data
70
70
  #
71
- def path(name, data = nil)
72
- RouteLookup.new.path(name, data)
71
+ def path(name_or_path, data = nil)
72
+ if name_or_path.is_a?(String)
73
+ return name_or_path
74
+ elsif name_or_path.is_a?(Hash)
75
+ RouteLookup.new.group(name_or_path.keys[0]).path(name_or_path.values[0], data)
76
+ else
77
+ RouteLookup.new.path(name_or_path, data)
78
+ end
73
79
  end
74
80
 
75
81
  # Looks up a route grouping
@@ -1,13 +1,11 @@
1
1
  libdir = File.dirname(__FILE__)
2
2
  $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
3
3
 
4
- # Gems
4
+ # Gems
5
5
  require 'find'
6
6
  require 'rack'
7
7
  require 'rack/file'
8
8
  require 'logger'
9
9
  require 'cgi'
10
10
 
11
- # Base
12
11
  require 'core/base'
13
- include Pakyow