pakyow-core 0.9.1 → 0.10.0

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.
@@ -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