callable_tree 0.3.5 → 0.3.6

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 83716fbdef2881db33e8f046f056a17d8a8866423951493902088bf1af53218f
4
- data.tar.gz: 8906217b71482e1717798329d172640a50f7cc73613a2187beba0702bf8b8d74
3
+ metadata.gz: 2a83d353d4049c06aa0a0d5f18f56c5c6d0d909cd4a54f6bbcba7faf4e835c0f
4
+ data.tar.gz: ab803f4e8b613a0ceb5e4d3ca21d38e1a5cf2a238db61384c0ec85b437fd7d73
5
5
  SHA512:
6
- metadata.gz: 5e5ece858eb3347c41ea5f573e37c972d1a127d9fa234cd2512b18ef9e882b33d0da900b46c8f8e539fcee36fccb6643d21bb0945169019e7734232907c412c1
7
- data.tar.gz: ce58af4b926c9201f4133f02da848dcfff7962f9fa08588c1d4b4b61765b9c5ffaf03f2cfb4367da7d14a80bc1dcd55ea4b53de39d4075be25ef6e2abaf9ae7e
6
+ metadata.gz: 27dd59b36d4ebc99395df901a900d72510928f5f4a9603405b83f54d0566652fda2253bcda7bf6efee1ad0363919c5ec7bb63a1ec1e0efc488e656d6ff1bce3a
7
+ data.tar.gz: 3029f92901053688715cffce367d0e44f01402743413dfd38dc52c6c63221094fe2d3774cf2b1b98d66b84dd6837c8d6e6430c228ce3f196e60f9222286a3a56
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.3.6] - 2022-03-29
4
+
5
+ - (Experimental) Add `CallableTree::Node::Hooks::Matcher`.
6
+ Using this together with `CallableTree::Node::Hooks::Caller` helps to output logs. See `examples/builder/logging.rb` for details.
7
+
3
8
  ## [0.3.5] - 2022-03-20
4
9
 
5
10
  - Add `CallableTree::Node::Internal#seekable?` as an alias for `CallableTree::Node::Internal#seek?`.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- callable_tree (0.3.5)
4
+ callable_tree (0.3.6)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -568,20 +568,20 @@ Run `examples/logging.rb`:
568
568
  ---
569
569
  ```
570
570
 
571
- #### `CallableTree::Node::Hooks::Call` (experimental)
571
+ #### `CallableTree::Node::Hooks::Caller` (experimental)
572
572
 
573
573
  `examples/hooks-call.rb`:
574
574
  ```ruby
575
575
  module Node
576
576
  class HooksSample
577
577
  include CallableTree::Node::Internal
578
- prepend CallableTree::Node::Hooks::Call
578
+ prepend CallableTree::Node::Hooks::Caller
579
579
  end
580
580
  end
581
581
 
582
582
  Node::HooksSample.new
583
- .before_call do |input, **_options|
584
- puts "before_call input: #{input}";
583
+ .before_caller do |input, **_options|
584
+ puts "before_caller input: #{input}";
585
585
  input + 1
586
586
  end
587
587
  .append(
@@ -591,14 +591,14 @@ Node::HooksSample.new
591
591
  input * 2
592
592
  end
593
593
  )
594
- .around_call do |input, **_options, &block|
595
- puts "around_call input: #{input}"
594
+ .around_caller do |input, **_options, &block|
595
+ puts "around_caller input: #{input}"
596
596
  output = block.call
597
- puts "around_call output: #{output}"
597
+ puts "around_caller output: #{output}"
598
598
  output * input
599
599
  end
600
- .after_call do |output, **_options|
601
- puts "after_call output: #{output}"
600
+ .after_caller do |output, **_options|
601
+ puts "after_caller output: #{output}"
602
602
  output * 2
603
603
  end
604
604
  .tap do |tree|
@@ -608,14 +608,14 @@ Node::HooksSample.new
608
608
  end
609
609
  ```
610
610
 
611
- Run `examples/hooks-call.rb`:
611
+ Run `examples/hooks-caller.rb`:
612
612
  ```sh
613
- % ruby examples/hooks-call.rb
614
- before_call input: 1
613
+ % ruby examples/hooks-caller.rb
614
+ before_caller input: 1
615
615
  external input: 2
616
- around_call input: 2
617
- around_call output: 4
618
- after_call output: 8
616
+ around_caller input: 2
617
+ around_caller output: 4
618
+ after_caller output: 8
619
619
  result: 16
620
620
  ```
621
621
 
@@ -10,8 +10,8 @@ Root =
10
10
 
11
11
  Root
12
12
  .new
13
- .before_call do |input, **_options|
14
- puts "before_call input: #{input}"
13
+ .before_caller do |input, **_options|
14
+ puts "before_caller input: #{input}"
15
15
  input + 1
16
16
  end
17
17
  .append(
@@ -21,14 +21,14 @@ Root
21
21
  input * 2
22
22
  end
23
23
  )
24
- .around_call do |input, **_options, &block|
25
- puts "around_call input: #{input}"
24
+ .around_caller do |input, **_options, &block|
25
+ puts "around_caller input: #{input}"
26
26
  output = block.call
27
- puts "around_call output: #{output}"
27
+ puts "around_caller output: #{output}"
28
28
  output * input
29
29
  end
30
- .after_call do |output, **_options|
31
- puts "after_call output: #{output}"
30
+ .after_caller do |output, **_options|
31
+ puts "after_caller output: #{output}"
32
32
  output * 2
33
33
  end
34
34
  .tap do |tree|
@@ -4,89 +4,85 @@ require 'callable_tree'
4
4
  require 'json'
5
5
  require 'rexml/document'
6
6
 
7
- module JSONParser
8
- def self.build
9
- CallableTree::Node::Internal::Builder
10
- .new
11
- .matcher do |input, **_options|
12
- File.extname(input) == '.json'
13
- end
14
- .caller do |input, **options, &block|
15
- File.open(input) do |file|
16
- json = ::JSON.load(file)
17
- # The following block call is equivalent to calling `super` in the class style.
18
- block.call(json, **options)
19
- end
20
- end
21
- .terminator do
22
- true
23
- end
24
- .build
7
+ JSONParser =
8
+ CallableTree::Node::Internal::Builder
9
+ .new
10
+ .matcher do |input, **_options|
11
+ File.extname(input) == '.json'
25
12
  end
26
- end
27
-
28
- module XMLParser
29
- def self.build
30
- CallableTree::Node::Internal::Builder
31
- .new
32
- .matcher do |input, **_options|
33
- File.extname(input) == '.xml'
34
- end
35
- .caller do |input, **options, &block|
36
- File.open(input) do |file|
37
- # The following block call is equivalent to calling `super` in the class style.
38
- block.call(REXML::Document.new(file), **options)
39
- end
40
- end
41
- .terminator do
42
- true
43
- end
44
- .build
13
+ .caller do |input, **options, &block|
14
+ File.open(input) do |file|
15
+ json = ::JSON.load(file)
16
+ # The following block call is equivalent to calling `super` in the class style.
17
+ block.call(json, **options)
18
+ end
45
19
  end
46
- end
20
+ .terminator do
21
+ true
22
+ end
23
+ .build
47
24
 
48
- module JSONScraper
49
- def self.build(type)
50
- CallableTree::Node::External::Builder
51
- .new
52
- .matcher do |input, **_options|
53
- !!input[type.to_s]
54
- end
55
- .caller do |input, **_options|
56
- input[type.to_s]
57
- .map { |element| [element['name'], element['emoji']] }
58
- .to_h
59
- end
60
- .build
25
+ XMLParser =
26
+ CallableTree::Node::Internal::Builder
27
+ .new
28
+ .matcher do |input, **_options|
29
+ File.extname(input) == '.xml'
30
+ end
31
+ .caller do |input, **options, &block|
32
+ File.open(input) do |file|
33
+ # The following block call is equivalent to calling `super` in the class style.
34
+ block.call(REXML::Document.new(file), **options)
35
+ end
61
36
  end
37
+ .terminator do
38
+ true
39
+ end
40
+ .build
41
+
42
+ def build_json_scraper(type)
43
+ CallableTree::Node::External::Builder
44
+ .new
45
+ .matcher do |input, **_options|
46
+ !!input[type.to_s]
47
+ end
48
+ .caller do |input, **_options|
49
+ input[type.to_s]
50
+ .map { |element| [element['name'], element['emoji']] }
51
+ .to_h
52
+ end
53
+ .build
62
54
  end
63
55
 
64
- module XMLScraper
65
- def self.build(type)
66
- CallableTree::Node::External::Builder
67
- .new
68
- .matcher do |input, **_options|
69
- !input.get_elements("//#{type}").empty?
70
- end
71
- .caller do |input, **_options|
72
- input
73
- .get_elements("//#{type}")
74
- .first
75
- .map { |element| [element['name'], element['emoji']] }
76
- .to_h
77
- end
78
- .build
79
- end
56
+ AnimalsJSONScraper = build_json_scraper(:animals)
57
+ FruitsJSONScraper = build_json_scraper(:fruits)
58
+
59
+ def build_xml_scraper(type)
60
+ CallableTree::Node::External::Builder
61
+ .new
62
+ .matcher do |input, **_options|
63
+ !input.get_elements("//#{type}").empty?
64
+ end
65
+ .caller do |input, **_options|
66
+ input
67
+ .get_elements("//#{type}")
68
+ .first
69
+ .map { |element| [element['name'], element['emoji']] }
70
+ .to_h
71
+ end
72
+ .build
80
73
  end
81
74
 
75
+ AnimalsXMLScraper = build_xml_scraper(:animals)
76
+ FruitsXMLScraper = build_xml_scraper(:fruits)
77
+
82
78
  tree = CallableTree::Node::Root.new.seekable.append(
83
- JSONParser.build.new.seekable.append(
84
- JSONScraper.build(:animals).new,
85
- JSONScraper.build(:fruits).new
79
+ JSONParser.new.seekable.append(
80
+ AnimalsJSONScraper.new,
81
+ FruitsJSONScraper.new
86
82
  ),
87
- XMLParser.build.new.seekable.append(
88
- XMLScraper.build(:animals).new,
89
- XMLScraper.build(:fruits).new
83
+ XMLParser.new.seekable.append(
84
+ AnimalsXMLScraper.new,
85
+ FruitsXMLScraper.new
90
86
  )
91
87
  )
92
88
 
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'callable_tree'
4
+ require 'json'
5
+ require 'rexml/document'
6
+
7
+ JSONParser =
8
+ CallableTree::Node::Internal::Builder
9
+ .new
10
+ .matcher do |input, **_options|
11
+ File.extname(input) == '.json'
12
+ end
13
+ .caller do |input, **options, &block|
14
+ File.open(input) do |file|
15
+ json = ::JSON.load(file)
16
+ # The following block call is equivalent to calling `super` in the class style.
17
+ block.call(json, **options)
18
+ end
19
+ end
20
+ .terminator do
21
+ true
22
+ end
23
+ .hookable
24
+ .build
25
+
26
+ XMLParser =
27
+ CallableTree::Node::Internal::Builder
28
+ .new
29
+ .matcher do |input, **_options|
30
+ File.extname(input) == '.xml'
31
+ end
32
+ .caller do |input, **options, &block|
33
+ File.open(input) do |file|
34
+ # The following block call is equivalent to calling `super` in the class style.
35
+ block.call(REXML::Document.new(file), **options)
36
+ end
37
+ end
38
+ .terminator do
39
+ true
40
+ end
41
+ .hookable
42
+ .build
43
+
44
+ def build_json_scraper(type)
45
+ CallableTree::Node::External::Builder
46
+ .new
47
+ .matcher do |input, **_options|
48
+ !!input[type.to_s]
49
+ end
50
+ .caller do |input, **_options|
51
+ input[type.to_s]
52
+ .map { |element| [element['name'], element['emoji']] }
53
+ .to_h
54
+ end
55
+ .hookable
56
+ .build
57
+ end
58
+
59
+ AnimalsJSONScraper = build_json_scraper(:animals)
60
+ FruitsJSONScraper = build_json_scraper(:fruits)
61
+
62
+ def build_xml_scraper(type)
63
+ CallableTree::Node::External::Builder
64
+ .new
65
+ .matcher do |input, **_options|
66
+ !input.get_elements("//#{type}").empty?
67
+ end
68
+ .caller do |input, **_options|
69
+ input
70
+ .get_elements("//#{type}")
71
+ .first
72
+ .map { |element| [element['name'], element['emoji']] }
73
+ .to_h
74
+ end
75
+ .hookable
76
+ .build
77
+ end
78
+
79
+ AnimalsXMLScraper = build_xml_scraper(:animals)
80
+ FruitsXMLScraper = build_xml_scraper(:fruits)
81
+
82
+ loggable = proc do |node|
83
+ indent_size = 2
84
+ blank = ' '
85
+ list_style = '*'
86
+
87
+ node.after_matcher! do |matched, _node_:, **|
88
+ prefix = list_style.rjust(_node_.depth * indent_size - indent_size + list_style.length, blank)
89
+ puts "#{prefix} #{_node_.identity}: [matched: #{matched}]"
90
+ matched
91
+ end
92
+
93
+ if node.is_a?(CallableTree::Node::External)
94
+ input_label = 'Input :'
95
+ output_label = 'Output:'
96
+
97
+ node
98
+ .before_caller! do |input, *, _node_:, **|
99
+ input_prefix = input_label.rjust(_node_.depth * indent_size + input_label.length, blank)
100
+ puts "#{input_prefix} #{input}"
101
+ input
102
+ end
103
+ .after_caller! do |output, _node_:, **|
104
+ output_prefix = output_label.rjust(_node_.depth * indent_size + output_label.length, blank)
105
+ puts "#{output_prefix} #{output}"
106
+ output
107
+ end
108
+ end
109
+ end
110
+
111
+ tree = CallableTree::Node::Root.new.seekable.append(
112
+ JSONParser.new.tap(&loggable).seekable.append(
113
+ AnimalsJSONScraper.new.tap(&loggable).verbosify,
114
+ FruitsJSONScraper.new.tap(&loggable).verbosify
115
+ ),
116
+ XMLParser.new.tap(&loggable).seekable.append(
117
+ AnimalsXMLScraper.new.tap(&loggable).verbosify,
118
+ FruitsXMLScraper.new.tap(&loggable).verbosify
119
+ )
120
+ )
121
+
122
+ Dir.glob("#{__dir__}/../docs/*") do |file|
123
+ options = { foo: :bar }
124
+ pp tree.call(file, **options)
125
+ puts '---'
126
+ end
@@ -5,14 +5,14 @@ require 'callable_tree'
5
5
  module Node
6
6
  class HooksSample
7
7
  include CallableTree::Node::Internal
8
- prepend CallableTree::Node::Hooks::Call
8
+ prepend CallableTree::Node::Hooks::Caller
9
9
  end
10
10
  end
11
11
 
12
12
  Node::HooksSample
13
13
  .new
14
- .before_call do |input, **_options|
15
- puts "before_call input: #{input}"
14
+ .before_caller do |input, **_options|
15
+ puts "before_caller input: #{input}"
16
16
  input + 1
17
17
  end
18
18
  .append(
@@ -22,14 +22,14 @@ Node::HooksSample
22
22
  input * 2
23
23
  end
24
24
  )
25
- .around_call do |input, **_options, &block|
26
- puts "around_call input: #{input}"
25
+ .around_caller do |input, **_options, &block|
26
+ puts "around_caller input: #{input}"
27
27
  output = block.call
28
- puts "around_call output: #{output}"
28
+ puts "around_caller output: #{output}"
29
29
  output * input
30
30
  end
31
- .after_call do |output, **_options|
32
- puts "after_call output: #{output}"
31
+ .after_caller do |output, **_options|
32
+ puts "after_caller output: #{output}"
33
33
  output * 2
34
34
  end
35
35
  .tap do |tree|
@@ -44,7 +44,10 @@ module CallableTree
44
44
  ::Class
45
45
  .new do
46
46
  include node_type
47
- prepend Hooks::Call if hookable
47
+ if hookable
48
+ prepend Hooks::Matcher
49
+ prepend Hooks::Caller
50
+ end
48
51
 
49
52
  if matcher
50
53
  define_method(:match?) do |*inputs, **options|
@@ -15,7 +15,7 @@ module CallableTree
15
15
  private
16
16
 
17
17
  def validate(matcher:, caller:, terminator:)
18
- raise Error 'caller is required' unless caller
18
+ raise Error, 'caller is required' unless caller
19
19
  end
20
20
  end
21
21
  end
@@ -3,7 +3,6 @@
3
3
  module CallableTree
4
4
  module Node
5
5
  module External
6
- # TODO: Add :inputs
7
6
  Output = Struct.new(:value, :options, :routes)
8
7
 
9
8
  module Verbose
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CallableTree
4
+ module Node
5
+ module Hooks
6
+ module Caller
7
+ def self.included(_subclass)
8
+ raise ::CallableTree::Error, "#{self} must be prepended"
9
+ end
10
+
11
+ def before_call(&block)
12
+ clone.before_call!(&block)
13
+ end
14
+
15
+ def before_call!(&block)
16
+ before_caller_callbacks << block
17
+ self
18
+ end
19
+
20
+ def around_call(&block)
21
+ clone.around_call!(&block)
22
+ end
23
+
24
+ def around_call!(&block)
25
+ around_caller_callbacks << block
26
+ self
27
+ end
28
+
29
+ def after_call(&block)
30
+ clone.after_call!(&block)
31
+ end
32
+
33
+ def after_call!(&block)
34
+ after_caller_callbacks << block
35
+ self
36
+ end
37
+
38
+ alias before_caller before_call
39
+ alias before_caller! before_call!
40
+ alias around_caller around_call
41
+ alias around_caller! around_call!
42
+ alias after_caller after_call
43
+ alias after_caller! after_call!
44
+
45
+ def call(*inputs, **options)
46
+ input_head, *input_tail = inputs
47
+
48
+ input_head = before_caller_callbacks.reduce(input_head) do |input_head, callable|
49
+ callable.call(input_head, *input_tail, **options, _node_: self)
50
+ end
51
+
52
+ output =
53
+ if around_caller_callbacks.empty?
54
+ super(input_head, *input_tail, **options)
55
+ else
56
+ around_caller_callbacks_head, *around_caller_callbacks_tail = around_caller_callbacks
57
+ caller = proc { super(input_head, *input_tail, **options) }
58
+
59
+ output =
60
+ around_caller_callbacks_head
61
+ .call(
62
+ input_head,
63
+ *input_tail,
64
+ **options,
65
+ _node_: self
66
+ ) { caller.call }
67
+
68
+ around_caller_callbacks_tail.reduce(output) do |output, callable|
69
+ callable.call(
70
+ input_head,
71
+ *input_tail,
72
+ **options,
73
+ _node_: self
74
+ ) { output }
75
+ end
76
+ end
77
+
78
+ after_caller_callbacks.reduce(output) do |output, callable|
79
+ callable.call(output, **options, _node_: self)
80
+ end
81
+ end
82
+
83
+ def before_caller_callbacks
84
+ @before_caller_callbacks ||= []
85
+ end
86
+
87
+ def around_caller_callbacks
88
+ @around_caller_callbacks ||= []
89
+ end
90
+
91
+ def after_caller_callbacks
92
+ @after_caller_callbacks ||= []
93
+ end
94
+
95
+ private
96
+
97
+ attr_writer :before_caller_callbacks, :around_caller_callbacks, :after_caller_callbacks
98
+
99
+ def initialize_copy(_node)
100
+ super
101
+ self.before_caller_callbacks = before_caller_callbacks.map(&:itself)
102
+ self.around_caller_callbacks = around_caller_callbacks.map(&:itself)
103
+ self.after_caller_callbacks = after_caller_callbacks.map(&:itself)
104
+ end
105
+ end
106
+
107
+ Call = Caller # backward compatibility
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CallableTree
4
+ module Node
5
+ module Hooks
6
+ module Matcher
7
+ def self.included(_subclass)
8
+ raise ::CallableTree::Error, "#{self} must be prepended"
9
+ end
10
+
11
+ def before_matcher(&block)
12
+ clone.before_matcher!(&block)
13
+ end
14
+
15
+ def before_matcher!(&block)
16
+ before_matcher_callbacks << block
17
+ self
18
+ end
19
+
20
+ def around_matcher(&block)
21
+ clone.around_matcher!(&block)
22
+ end
23
+
24
+ def around_matcher!(&block)
25
+ around_matcher_callbacks << block
26
+ self
27
+ end
28
+
29
+ def after_matcher(&block)
30
+ clone.after_matcher!(&block)
31
+ end
32
+
33
+ def after_matcher!(&block)
34
+ after_matcher_callbacks << block
35
+ self
36
+ end
37
+
38
+ def match?(*inputs, **options)
39
+ input_head, *input_tail = inputs
40
+
41
+ input_head = before_matcher_callbacks.reduce(input_head) do |input_head, callable|
42
+ callable.call(input_head, *input_tail, **options, _node_: self)
43
+ end
44
+
45
+ matched =
46
+ if around_matcher_callbacks.empty?
47
+ super(input_head, *input_tail, **options)
48
+ else
49
+ around_matcher_callbacks_head, *around_matcher_callbacks_tail = around_matcher_callbacks
50
+ matcher = proc { super(input_head, *input_tail, **options) }
51
+
52
+ matched =
53
+ around_matcher_callbacks_head
54
+ .call(
55
+ input_head,
56
+ *input_tail,
57
+ **options,
58
+ _node_: self
59
+ ) { matcher.call }
60
+
61
+ around_matcher_callbacks_tail.reduce(matched) do |matched, callable|
62
+ callable.call(
63
+ input_head,
64
+ *input_tail,
65
+ **options,
66
+ _node_: self
67
+ ) { matched }
68
+ end
69
+ end
70
+
71
+ after_matcher_callbacks.reduce(matched) do |matched, callable|
72
+ callable.call(matched, **options, _node_: self)
73
+ end
74
+ end
75
+
76
+ def before_matcher_callbacks
77
+ @before_matcher_callbacks ||= []
78
+ end
79
+
80
+ def around_matcher_callbacks
81
+ @around_matcher_callbacks ||= []
82
+ end
83
+
84
+ def after_matcher_callbacks
85
+ @after_matcher_callbacks ||= []
86
+ end
87
+
88
+ private
89
+
90
+ attr_writer :before_matcher_callbacks, :around_matcher_callbacks, :after_matcher_callbacks
91
+
92
+ def initialize_copy(_node)
93
+ super
94
+ self.before_matcher_callbacks = before_matcher_callbacks.map(&:itself)
95
+ self.around_matcher_callbacks = around_matcher_callbacks.map(&:itself)
96
+ self.after_matcher_callbacks = after_matcher_callbacks.map(&:itself)
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -98,9 +98,9 @@ module CallableTree
98
98
  end
99
99
  end
100
100
 
101
- alias_method :seekable?, :seek?
102
- alias_method :seekable, :seek
103
- alias_method :seekable!, :seek!
101
+ alias seekable? seek?
102
+ alias seekable seek
103
+ alias seekable! seek!
104
104
 
105
105
  def broadcast?
106
106
  strategy.is_a?(Strategy::Broadcast)
@@ -122,9 +122,9 @@ module CallableTree
122
122
  end
123
123
  end
124
124
 
125
- alias_method :broadcastable?, :broadcast?
126
- alias_method :broadcastable, :broadcast
127
- alias_method :broadcastable!, :broadcast!
125
+ alias broadcastable? broadcast?
126
+ alias broadcastable broadcast
127
+ alias broadcastable! broadcast!
128
128
 
129
129
  def compose?
130
130
  strategy.is_a?(Strategy::Compose)
@@ -146,9 +146,9 @@ module CallableTree
146
146
  end
147
147
  end
148
148
 
149
- alias_method :composable?, :compose?
150
- alias_method :composable, :compose
151
- alias_method :composable!, :compose!
149
+ alias composable? compose?
150
+ alias composable compose
151
+ alias composable! compose!
152
152
 
153
153
  def outline(&block)
154
154
  key = block ? block.call(self) : identity
@@ -4,7 +4,8 @@ module CallableTree
4
4
  module Node
5
5
  class Root
6
6
  include Internal
7
- prepend Hooks::Call
7
+ prepend Hooks::Matcher
8
+ prepend Hooks::Caller
8
9
 
9
10
  def self.inherited(subclass)
10
11
  raise ::CallableTree::Error, "#{subclass} cannot inherit #{self}"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CallableTree
4
- VERSION = '0.3.5'
4
+ VERSION = '0.3.6'
5
5
  end
data/lib/callable_tree.rb CHANGED
@@ -7,7 +7,8 @@ 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'
10
+ require_relative 'callable_tree/node/hooks/matcher'
11
+ require_relative 'callable_tree/node/hooks/caller'
11
12
  require_relative 'callable_tree/node/internal/strategy'
12
13
  require_relative 'callable_tree/node/internal/strategy/broadcast'
13
14
  require_relative 'callable_tree/node/internal/strategy/seek'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: callable_tree
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.5
4
+ version: 0.3.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - jsmmr
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-03-20 00:00:00.000000000 Z
11
+ date: 2022-03-29 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Builds a tree by linking callable nodes. The nodes that match the conditions
14
14
  are called in a chain from the root node to the leaf node. These are like nested
@@ -33,16 +33,17 @@ files:
33
33
  - bin/console
34
34
  - bin/setup
35
35
  - callable_tree.gemspec
36
- - examples/builder/hooks-call.rb
36
+ - examples/builder/hooks-caller.rb
37
37
  - examples/builder/internal-broadcastable.rb
38
38
  - examples/builder/internal-composable.rb
39
39
  - examples/builder/internal-seekable.rb
40
+ - examples/builder/logging.rb
40
41
  - examples/docs/animals.json
41
42
  - examples/docs/animals.xml
42
43
  - examples/docs/fruits.json
43
44
  - examples/docs/fruits.xml
44
45
  - examples/external-verbosify.rb
45
- - examples/hooks-call.rb
46
+ - examples/hooks-caller.rb
46
47
  - examples/identity.rb
47
48
  - examples/internal-broadcastable.rb
48
49
  - examples/internal-composable.rb
@@ -54,7 +55,8 @@ files:
54
55
  - lib/callable_tree/node/external.rb
55
56
  - lib/callable_tree/node/external/builder.rb
56
57
  - lib/callable_tree/node/external/verbose.rb
57
- - lib/callable_tree/node/hooks/call.rb
58
+ - lib/callable_tree/node/hooks/caller.rb
59
+ - lib/callable_tree/node/hooks/matcher.rb
58
60
  - lib/callable_tree/node/internal.rb
59
61
  - lib/callable_tree/node/internal/builder.rb
60
62
  - lib/callable_tree/node/internal/strategy.rb
@@ -69,7 +71,7 @@ licenses:
69
71
  metadata:
70
72
  homepage_uri: https://github.com/jsmmr/ruby_callable_tree
71
73
  source_code_uri: https://github.com/jsmmr/ruby_callable_tree
72
- changelog_uri: https://github.com/jsmmr/ruby_callable_tree/blob/v0.3.5/CHANGELOG.md
74
+ changelog_uri: https://github.com/jsmmr/ruby_callable_tree/blob/v0.3.6/CHANGELOG.md
73
75
  post_install_message:
74
76
  rdoc_options: []
75
77
  require_paths:
@@ -1,81 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module CallableTree
4
- module Node
5
- module Hooks
6
- module Call
7
- def self.included(_subclass)
8
- raise ::CallableTree::Error, "#{self} must be prepended"
9
- end
10
-
11
- def before_call(&block)
12
- clone.before_call!(&block)
13
- end
14
-
15
- def before_call!(&block)
16
- before_callbacks << block
17
- self
18
- end
19
-
20
- def around_call(&block)
21
- clone.around_call!(&block)
22
- end
23
-
24
- def around_call!(&block)
25
- around_callbacks << block
26
- self
27
- end
28
-
29
- def after_call(&block)
30
- clone.after_call!(&block)
31
- end
32
-
33
- def after_call!(&block)
34
- after_callbacks << block
35
- self
36
- end
37
-
38
- def call(*inputs, **options)
39
- input_head, *input_tail = inputs
40
-
41
- input_head = before_callbacks.reduce(input_head) do |input_head, callable|
42
- callable.call(input_head, *input_tail, self, **options)
43
- end
44
-
45
- output = super(input_head, *input_tail, **options)
46
-
47
- output = around_callbacks.reduce(output) do |output, callable|
48
- callable.call(input_head, *input_tail, self, **options) { output }
49
- end
50
-
51
- after_callbacks.reduce(output) do |output, callable|
52
- callable.call(output, self, **options)
53
- end
54
- end
55
-
56
- def before_callbacks
57
- @before_callbacks ||= []
58
- end
59
-
60
- def around_callbacks
61
- @around_callbacks ||= []
62
- end
63
-
64
- def after_callbacks
65
- @after_callbacks ||= []
66
- end
67
-
68
- private
69
-
70
- attr_writer :before_callbacks, :around_callbacks, :after_callbacks
71
-
72
- def initialize_copy(_node)
73
- super
74
- self.before_callbacks = before_callbacks.map(&:itself)
75
- self.around_callbacks = around_callbacks.map(&:itself)
76
- self.after_callbacks = after_callbacks.map(&:itself)
77
- end
78
- end
79
- end
80
- end
81
- end