callable_tree 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/Gemfile.lock +1 -1
- data/README.md +124 -13
- data/callable_tree.gemspec +3 -3
- data/examples/example1.rb +1 -1
- data/examples/example2.rb +1 -1
- data/examples/example3.rb +1 -1
- data/examples/example4.rb +1 -1
- data/examples/example6.rb +101 -0
- data/lib/callable_tree.rb +3 -1
- data/lib/callable_tree/node/internal.rb +20 -38
- data/lib/callable_tree/node/internal/broadcast.rb +19 -0
- data/lib/callable_tree/node/internal/seek.rb +23 -0
- data/lib/callable_tree/version.rb +1 -1
- metadata +8 -6
- data/lib/callable_tree/node/branch.rb +0 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ea52457dd99aca79ec45ac97716f53824b14dde4d479486b9d9fa6571a714c76
|
4
|
+
data.tar.gz: 4fa5ee37a4a061b7c92f3373131b588bd30f12a351f344646dab2ec2d1089718
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5f6e91b80e81f89d0e8f1c15ac5043de2b100245232de6b3584e900d1378952ad91442e4a55f80c59cfe8a01e5a9b34cf277b3a213290cf0b5aa8e0985edc7ca
|
7
|
+
data.tar.gz: 2a89b0e60761fa826c1e083b34f24138693c9f44743c0c3c018f6dcbf330a6471481421dc9c99b4f4d5ae2f410aaeec293bed4ed46f10f28482280ea582f895a
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -136,7 +136,7 @@ tree = CallableTree::Node::Root.new.append(
|
|
136
136
|
|
137
137
|
Dir.glob(__dir__ + '/docs/*') do |file|
|
138
138
|
options = { foo: :bar }
|
139
|
-
|
139
|
+
pp tree.call(file, **options)
|
140
140
|
puts '---'
|
141
141
|
end
|
142
142
|
```
|
@@ -181,13 +181,25 @@ tree = CallableTree::Node::Root.new.append(
|
|
181
181
|
Run `examples/example2.rb`:
|
182
182
|
```sh
|
183
183
|
% ruby examples/example2.rb
|
184
|
-
#<struct CallableTree::Node::External::Output
|
184
|
+
#<struct CallableTree::Node::External::Output
|
185
|
+
value={"Dog"=>"🐶", "Cat"=>"🐱"},
|
186
|
+
options={:foo=>:bar},
|
187
|
+
routes=[Node::JSON::Scraper, Node::JSON::Parser, CallableTree::Node::Root]>
|
185
188
|
---
|
186
|
-
#<struct CallableTree::Node::External::Output
|
189
|
+
#<struct CallableTree::Node::External::Output
|
190
|
+
value={"Dog"=>"🐶", "Cat"=>"🐱"},
|
191
|
+
options={:foo=>:bar},
|
192
|
+
routes=[Node::XML::Scraper, Node::XML::Parser, CallableTree::Node::Root]>
|
187
193
|
---
|
188
|
-
#<struct CallableTree::Node::External::Output
|
194
|
+
#<struct CallableTree::Node::External::Output
|
195
|
+
value={"Red Apple"=>"🍎", "Green Apple"=>"🍏"},
|
196
|
+
options={:foo=>:bar},
|
197
|
+
routes=[Node::JSON::Scraper, Node::JSON::Parser, CallableTree::Node::Root]>
|
189
198
|
---
|
190
|
-
#<struct CallableTree::Node::External::Output
|
199
|
+
#<struct CallableTree::Node::External::Output
|
200
|
+
value={"Red Apple"=>"🍎", "Green Apple"=>"🍏"},
|
201
|
+
options={:foo=>:bar},
|
202
|
+
routes=[Node::XML::Scraper, Node::XML::Parser, CallableTree::Node::Root]>
|
191
203
|
---
|
192
204
|
```
|
193
205
|
|
@@ -257,13 +269,45 @@ end
|
|
257
269
|
Run `examples/example3.rb`:
|
258
270
|
```sh
|
259
271
|
% ruby examples/example3.rb
|
260
|
-
#<struct CallableTree::Node::External::Output
|
272
|
+
#<struct CallableTree::Node::External::Output
|
273
|
+
value={"Dog"=>"🐶", "Cat"=>"🐱"},
|
274
|
+
options={:foo=>:bar},
|
275
|
+
routes=
|
276
|
+
[#<Node::Identity:0x00007fb4378a9718
|
277
|
+
@klass=Node::JSON::Scraper,
|
278
|
+
@type=:animals>,
|
279
|
+
Node::JSON::Parser,
|
280
|
+
CallableTree::Node::Root]>
|
261
281
|
---
|
262
|
-
#<struct CallableTree::Node::External::Output
|
282
|
+
#<struct CallableTree::Node::External::Output
|
283
|
+
value={"Dog"=>"🐶", "Cat"=>"🐱"},
|
284
|
+
options={:foo=>:bar},
|
285
|
+
routes=
|
286
|
+
[#<Node::Identity:0x00007fb41002b6d0
|
287
|
+
@klass=Node::XML::Scraper,
|
288
|
+
@type=:animals>,
|
289
|
+
Node::XML::Parser,
|
290
|
+
CallableTree::Node::Root]>
|
263
291
|
---
|
264
|
-
#<struct CallableTree::Node::External::Output
|
292
|
+
#<struct CallableTree::Node::External::Output
|
293
|
+
value={"Red Apple"=>"🍎", "Green Apple"=>"🍏"},
|
294
|
+
options={:foo=>:bar},
|
295
|
+
routes=
|
296
|
+
[#<Node::Identity:0x00007fb41001b3e8
|
297
|
+
@klass=Node::JSON::Scraper,
|
298
|
+
@type=:fruits>,
|
299
|
+
Node::JSON::Parser,
|
300
|
+
CallableTree::Node::Root]>
|
265
301
|
---
|
266
|
-
#<struct CallableTree::Node::External::Output
|
302
|
+
#<struct CallableTree::Node::External::Output
|
303
|
+
value={"Red Apple"=>"🍎", "Green Apple"=>"🍏"},
|
304
|
+
options={:foo=>:bar},
|
305
|
+
routes=
|
306
|
+
[#<Node::Identity:0x00007fb410049d38
|
307
|
+
@klass=Node::XML::Scraper,
|
308
|
+
@type=:fruits>,
|
309
|
+
Node::XML::Parser,
|
310
|
+
CallableTree::Node::Root]>
|
267
311
|
---
|
268
312
|
```
|
269
313
|
|
@@ -351,21 +395,45 @@ Run `examples/example4.rb`:
|
|
351
395
|
* Node::JSON::Scraper(animals): [matched: true]
|
352
396
|
Input : {"animals"=>[{"name"=>"Dog", "emoji"=>"🐶"}, {"name"=>"Cat", "emoji"=>"🐱"}]}
|
353
397
|
Output: {"Dog"=>"🐶", "Cat"=>"🐱"}
|
354
|
-
#<struct CallableTree::Node::External::Output
|
398
|
+
#<struct CallableTree::Node::External::Output
|
399
|
+
value={"Dog"=>"🐶", "Cat"=>"🐱"},
|
400
|
+
options={:foo=>:bar},
|
401
|
+
routes=
|
402
|
+
[#<Node::Identity:0x00007ffd840347b8
|
403
|
+
@klass=Node::JSON::Scraper,
|
404
|
+
@type=:animals>,
|
405
|
+
Node::JSON::Parser,
|
406
|
+
CallableTree::Node::Root]>
|
355
407
|
---
|
356
408
|
* Node::JSON::Parser: [matched: false]
|
357
409
|
* Node::XML::Parser: [matched: true]
|
358
410
|
* Node::XML::Scraper(animals): [matched: true]
|
359
411
|
Input : <root><animals><animal emoji='🐶' name='Dog'/><animal emoji='🐱' name='Cat'/></animals></root>
|
360
412
|
Output: {"Dog"=>"🐶", "Cat"=>"🐱"}
|
361
|
-
#<struct CallableTree::Node::External::Output
|
413
|
+
#<struct CallableTree::Node::External::Output
|
414
|
+
value={"Dog"=>"🐶", "Cat"=>"🐱"},
|
415
|
+
options={:foo=>:bar},
|
416
|
+
routes=
|
417
|
+
[#<Node::Identity:0x00007ffd7403f1f0
|
418
|
+
@klass=Node::XML::Scraper,
|
419
|
+
@type=:animals>,
|
420
|
+
Node::XML::Parser,
|
421
|
+
CallableTree::Node::Root]>
|
362
422
|
---
|
363
423
|
* Node::JSON::Parser: [matched: true]
|
364
424
|
* Node::JSON::Scraper(animals): [matched: false]
|
365
425
|
* Node::JSON::Scraper(fruits): [matched: true]
|
366
426
|
Input : {"fruits"=>[{"name"=>"Red Apple", "emoji"=>"🍎"}, {"name"=>"Green Apple", "emoji"=>"🍏"}]}
|
367
427
|
Output: {"Red Apple"=>"🍎", "Green Apple"=>"🍏"}
|
368
|
-
#<struct CallableTree::Node::External::Output
|
428
|
+
#<struct CallableTree::Node::External::Output
|
429
|
+
value={"Red Apple"=>"🍎", "Green Apple"=>"🍏"},
|
430
|
+
options={:foo=>:bar},
|
431
|
+
routes=
|
432
|
+
[#<Node::Identity:0x00007ffd8512bdf0
|
433
|
+
@klass=Node::JSON::Scraper,
|
434
|
+
@type=:fruits>,
|
435
|
+
Node::JSON::Parser,
|
436
|
+
CallableTree::Node::Root]>
|
369
437
|
---
|
370
438
|
* Node::JSON::Parser: [matched: false]
|
371
439
|
* Node::XML::Parser: [matched: true]
|
@@ -373,7 +441,15 @@ Run `examples/example4.rb`:
|
|
373
441
|
* Node::XML::Scraper(fruits): [matched: true]
|
374
442
|
Input : <root><fruits><fruit emoji='🍎' name='Red Apple'/><fruit emoji='🍏' name='Green Apple'/></fruits></root>
|
375
443
|
Output: {"Red Apple"=>"🍎", "Green Apple"=>"🍏"}
|
376
|
-
#<struct CallableTree::Node::External::Output
|
444
|
+
#<struct CallableTree::Node::External::Output
|
445
|
+
value={"Red Apple"=>"🍎", "Green Apple"=>"🍏"},
|
446
|
+
options={:foo=>:bar},
|
447
|
+
routes=
|
448
|
+
[#<Node::Identity:0x00007ffd8407a740
|
449
|
+
@klass=Node::XML::Scraper,
|
450
|
+
@type=:fruits>,
|
451
|
+
Node::XML::Parser,
|
452
|
+
CallableTree::Node::Root]>
|
377
453
|
---
|
378
454
|
```
|
379
455
|
|
@@ -427,6 +503,41 @@ after_call output: 8
|
|
427
503
|
result: 16
|
428
504
|
```
|
429
505
|
|
506
|
+
#### `CallableTree::Node::Internal#broadcast` (experimental)
|
507
|
+
|
508
|
+
If you want to call and output all child nodes of the internal node, call it. Broadcast strategy ignores the `terminate?` method of the child node.
|
509
|
+
|
510
|
+
`examples/example6.rb`:
|
511
|
+
```ruby
|
512
|
+
...
|
513
|
+
|
514
|
+
tree = CallableTree::Node::Root.new.append(
|
515
|
+
Node::JSON::Parser.new.append(
|
516
|
+
Node::JSON::Scraper.new(type: :animals),
|
517
|
+
Node::JSON::Scraper.new(type: :fruits)
|
518
|
+
).broadcast,
|
519
|
+
Node::XML::Parser.new.append(
|
520
|
+
Node::XML::Scraper.new(type: :animals),
|
521
|
+
Node::XML::Scraper.new(type: :fruits)
|
522
|
+
).broadcast
|
523
|
+
)
|
524
|
+
|
525
|
+
...
|
526
|
+
```
|
527
|
+
|
528
|
+
Run `examples/example6.rb`:
|
529
|
+
```sh
|
530
|
+
% ruby examples/example6.rb
|
531
|
+
[{"Dog"=>"🐶", "Cat"=>"🐱"}, nil]
|
532
|
+
---
|
533
|
+
[{"Dog"=>"🐶", "Cat"=>"🐱"}, nil]
|
534
|
+
---
|
535
|
+
[nil, {"Red Apple"=>"🍎", "Green Apple"=>"🍏"}]
|
536
|
+
---
|
537
|
+
[nil, {"Red Apple"=>"🍎", "Green Apple"=>"🍏"}]
|
538
|
+
---
|
539
|
+
```
|
540
|
+
|
430
541
|
## Contributing
|
431
542
|
|
432
543
|
Bug reports and pull requests are welcome on GitHub at https://github.com/jsmmr/callable_tree.
|
data/callable_tree.gemspec
CHANGED
@@ -8,15 +8,15 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.authors = ['jsmmr']
|
9
9
|
spec.email = ['jsmmr@icloud.com']
|
10
10
|
|
11
|
-
spec.summary = 'Builds a tree by linking callable nodes. The nodes that match the calling condition are called in a chain from the root node to the leaf node.
|
12
|
-
spec.description = 'Builds a tree by linking callable nodes. The nodes that match the calling condition are called in a chain from the root node to the leaf node.
|
11
|
+
spec.summary = 'Builds a tree by linking callable nodes. The nodes that match the calling condition are called in a chain from the root node to the leaf node. These are like nested case statements.'
|
12
|
+
spec.description = 'Builds a tree by linking callable nodes. The nodes that match the calling condition are called in a chain from the root node to the leaf node. These are like nested case statements.'
|
13
13
|
spec.homepage = 'https://github.com/jsmmr/ruby_callable_tree'
|
14
14
|
spec.license = 'MIT'
|
15
15
|
spec.required_ruby_version = Gem::Requirement.new('>= 2.4.0')
|
16
16
|
|
17
17
|
spec.metadata['homepage_uri'] = spec.homepage
|
18
18
|
spec.metadata['source_code_uri'] = 'https://github.com/jsmmr/ruby_callable_tree'
|
19
|
-
spec.metadata['changelog_uri'] = 'https://github.com/jsmmr/ruby_callable_tree/CHANGELOG.md'
|
19
|
+
spec.metadata['changelog_uri'] = 'https://github.com/jsmmr/ruby_callable_tree/blob/v#{version}/CHANGELOG.md'
|
20
20
|
|
21
21
|
# Specify which files should be added to the gem when it is released.
|
22
22
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
data/examples/example1.rb
CHANGED
data/examples/example2.rb
CHANGED
data/examples/example3.rb
CHANGED
data/examples/example4.rb
CHANGED
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'callable_tree'
|
2
|
+
require 'json'
|
3
|
+
require 'rexml/document'
|
4
|
+
|
5
|
+
module Node
|
6
|
+
module JSON
|
7
|
+
class Parser
|
8
|
+
include CallableTree::Node::Internal
|
9
|
+
|
10
|
+
def match?(input, **options)
|
11
|
+
File.extname(input) == '.json'
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(input, **options)
|
15
|
+
File.open(input) do |file|
|
16
|
+
json = ::JSON.load(file)
|
17
|
+
super(json, **options)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def terminate?(_output, **)
|
22
|
+
true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class Scraper
|
27
|
+
include CallableTree::Node::External
|
28
|
+
|
29
|
+
def initialize(type:)
|
30
|
+
@type = type
|
31
|
+
end
|
32
|
+
|
33
|
+
def match?(input, **options)
|
34
|
+
!!input[@type.to_s]
|
35
|
+
end
|
36
|
+
|
37
|
+
def call(input, **options)
|
38
|
+
input[@type.to_s]
|
39
|
+
.map { |element| [element['name'], element['emoji']] }
|
40
|
+
.to_h
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
module XML
|
46
|
+
class Parser
|
47
|
+
include CallableTree::Node::Internal
|
48
|
+
|
49
|
+
def match?(input, **options)
|
50
|
+
File.extname(input) == '.xml'
|
51
|
+
end
|
52
|
+
|
53
|
+
def call(input, **options)
|
54
|
+
File.open(input) do |file|
|
55
|
+
super(REXML::Document.new(file), **options)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def terminate?(_output, **)
|
60
|
+
true
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class Scraper
|
65
|
+
include CallableTree::Node::External
|
66
|
+
|
67
|
+
def initialize(type:)
|
68
|
+
@type = type
|
69
|
+
end
|
70
|
+
|
71
|
+
def match?(input, **options)
|
72
|
+
!input.get_elements("//#{@type}").empty?
|
73
|
+
end
|
74
|
+
|
75
|
+
def call(input, **options)
|
76
|
+
input
|
77
|
+
.get_elements("//#{@type}")
|
78
|
+
.first
|
79
|
+
.map { |element| [element['name'], element['emoji']] }
|
80
|
+
.to_h
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
tree = CallableTree::Node::Root.new.append(
|
87
|
+
Node::JSON::Parser.new.append(
|
88
|
+
Node::JSON::Scraper.new(type: :animals),
|
89
|
+
Node::JSON::Scraper.new(type: :fruits)
|
90
|
+
).broadcast,
|
91
|
+
Node::XML::Parser.new.append(
|
92
|
+
Node::XML::Scraper.new(type: :animals),
|
93
|
+
Node::XML::Scraper.new(type: :fruits)
|
94
|
+
).broadcast
|
95
|
+
)
|
96
|
+
|
97
|
+
Dir.glob(__dir__ + '/docs/*') do |file|
|
98
|
+
options = { foo: :bar }
|
99
|
+
pp tree.call(file, **options)
|
100
|
+
puts '---'
|
101
|
+
end
|
data/lib/callable_tree.rb
CHANGED
@@ -7,8 +7,10 @@ end
|
|
7
7
|
require 'forwardable'
|
8
8
|
require_relative 'callable_tree/version'
|
9
9
|
require_relative 'callable_tree/node'
|
10
|
+
require_relative 'callable_tree/node/hooks/call'
|
11
|
+
require_relative 'callable_tree/node/internal/broadcast'
|
12
|
+
require_relative 'callable_tree/node/internal/seek'
|
10
13
|
require_relative 'callable_tree/node/external/verbose'
|
11
14
|
require_relative 'callable_tree/node/external'
|
12
|
-
require_relative 'callable_tree/node/hooks/call'
|
13
15
|
require_relative 'callable_tree/node/internal'
|
14
16
|
require_relative 'callable_tree/node/root'
|
@@ -31,54 +31,36 @@ module CallableTree
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def call(input = nil, **options)
|
34
|
-
children
|
35
|
-
.lazy
|
36
|
-
.map { |node| Input.new(input, options, node) }
|
37
|
-
.select { |input| input.valid? }
|
38
|
-
.map { |input| input.call }
|
39
|
-
.select { |output| output.valid? }
|
40
|
-
.map { |output| output.call }
|
41
|
-
.first
|
34
|
+
strategy.call(children, input: input, options: options)
|
42
35
|
end
|
43
36
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
def valid?
|
52
|
-
@node.match?(@value, **@options)
|
53
|
-
end
|
54
|
-
|
55
|
-
def call
|
56
|
-
value = @node.call(@value, **@options)
|
57
|
-
Output.new(value, @options, @node)
|
37
|
+
def seek
|
38
|
+
if strategy.is_a?(Seek)
|
39
|
+
self
|
40
|
+
else
|
41
|
+
clone.tap do |node|
|
42
|
+
node.send(:strategy=, Seek.new)
|
43
|
+
end
|
58
44
|
end
|
59
45
|
end
|
60
46
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
def valid?
|
69
|
-
@node.terminate?(@value, **@options)
|
70
|
-
end
|
71
|
-
|
72
|
-
def call
|
73
|
-
@value
|
47
|
+
def broadcast
|
48
|
+
if strategy.is_a?(Broadcast)
|
49
|
+
self
|
50
|
+
else
|
51
|
+
clone.tap do |node|
|
52
|
+
node.send(:strategy=, Broadcast.new)
|
53
|
+
end
|
74
54
|
end
|
75
55
|
end
|
76
56
|
|
77
|
-
private_constant :Input, :Output
|
78
|
-
|
79
57
|
private
|
80
58
|
|
81
|
-
attr_writer :children
|
59
|
+
attr_writer :children, :strategy
|
60
|
+
|
61
|
+
def strategy
|
62
|
+
@strategy ||= Seek.new
|
63
|
+
end
|
82
64
|
|
83
65
|
def initialize_copy(_node)
|
84
66
|
super
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CallableTree
|
4
|
+
module Node
|
5
|
+
module Internal
|
6
|
+
class Broadcast
|
7
|
+
def call(nodes, input:, options:)
|
8
|
+
nodes.map do |node|
|
9
|
+
if node.match?(input, **options)
|
10
|
+
node.call(input, **options)
|
11
|
+
else
|
12
|
+
nil
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CallableTree
|
4
|
+
module Node
|
5
|
+
module Internal
|
6
|
+
class Seek
|
7
|
+
def call(nodes, input:, options:)
|
8
|
+
nodes
|
9
|
+
.lazy
|
10
|
+
.select { |node| node.match?(input, **options) }
|
11
|
+
.map do |node|
|
12
|
+
output = node.call(input, **options)
|
13
|
+
terminated = node.terminate?(output, **options)
|
14
|
+
[output, terminated]
|
15
|
+
end
|
16
|
+
.select { |_output, terminated| terminated }
|
17
|
+
.map { |output, _terminated| output }
|
18
|
+
.first
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
metadata
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: callable_tree
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- jsmmr
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-05-
|
11
|
+
date: 2021-05-27 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Builds a tree by linking callable nodes. The nodes that match the calling
|
14
|
-
condition are called in a chain from the root node to the leaf node.
|
14
|
+
condition are called in a chain from the root node to the leaf node. These are like
|
15
15
|
nested case statements.
|
16
16
|
email:
|
17
17
|
- jsmmr@icloud.com
|
@@ -41,13 +41,15 @@ files:
|
|
41
41
|
- examples/example3.rb
|
42
42
|
- examples/example4.rb
|
43
43
|
- examples/example5.rb
|
44
|
+
- examples/example6.rb
|
44
45
|
- lib/callable_tree.rb
|
45
46
|
- lib/callable_tree/node.rb
|
46
|
-
- lib/callable_tree/node/branch.rb
|
47
47
|
- lib/callable_tree/node/external.rb
|
48
48
|
- lib/callable_tree/node/external/verbose.rb
|
49
49
|
- lib/callable_tree/node/hooks/call.rb
|
50
50
|
- lib/callable_tree/node/internal.rb
|
51
|
+
- lib/callable_tree/node/internal/broadcast.rb
|
52
|
+
- lib/callable_tree/node/internal/seek.rb
|
51
53
|
- lib/callable_tree/node/root.rb
|
52
54
|
- lib/callable_tree/version.rb
|
53
55
|
homepage: https://github.com/jsmmr/ruby_callable_tree
|
@@ -56,7 +58,7 @@ licenses:
|
|
56
58
|
metadata:
|
57
59
|
homepage_uri: https://github.com/jsmmr/ruby_callable_tree
|
58
60
|
source_code_uri: https://github.com/jsmmr/ruby_callable_tree
|
59
|
-
changelog_uri: https://github.com/jsmmr/ruby_callable_tree/CHANGELOG.md
|
61
|
+
changelog_uri: https://github.com/jsmmr/ruby_callable_tree/blob/v#{version}/CHANGELOG.md
|
60
62
|
post_install_message:
|
61
63
|
rdoc_options: []
|
62
64
|
require_paths:
|
@@ -76,6 +78,6 @@ rubygems_version: 3.2.16
|
|
76
78
|
signing_key:
|
77
79
|
specification_version: 4
|
78
80
|
summary: Builds a tree by linking callable nodes. The nodes that match the calling
|
79
|
-
condition are called in a chain from the root node to the leaf node.
|
81
|
+
condition are called in a chain from the root node to the leaf node. These are like
|
80
82
|
nested case statements.
|
81
83
|
test_files: []
|
@@ -1,35 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module CallableTree
|
4
|
-
module Node
|
5
|
-
module Branch
|
6
|
-
attr_reader :parent
|
7
|
-
|
8
|
-
def ancestors
|
9
|
-
::Enumerator.new do |y|
|
10
|
-
node = self
|
11
|
-
while node = node&.parent
|
12
|
-
y << node
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
def routes
|
18
|
-
::Enumerator.new do |y|
|
19
|
-
y << self.class
|
20
|
-
ancestors.each { |node| y << node.class }
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def depth
|
25
|
-
parent.nil? ? 0 : parent.depth + 1
|
26
|
-
end
|
27
|
-
|
28
|
-
private
|
29
|
-
|
30
|
-
attr_writer :parent
|
31
|
-
end
|
32
|
-
|
33
|
-
private_constant :Branch
|
34
|
-
end
|
35
|
-
end
|