flow_object 0.1.2 → 0.2.1

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
  SHA1:
3
- metadata.gz: 6801b60384e39471a9fa4d760c6cb6d70965a118
4
- data.tar.gz: c3425e3bff1f135e63e2a608591a5818cd0287e4
3
+ metadata.gz: b6e87c3678c7dfc6a5b2293cdde82114f9f5630d
4
+ data.tar.gz: c1cd29c871342cc8a434cf60026fabd2a5d23394
5
5
  SHA512:
6
- metadata.gz: d0b6bd4523a523dfbec6a93df29bb0e42af0196b9e00b95f9370024fa99fb69217711eafa71fc2004c309bbe5d865982e53decf3a4120378e3fe4c9219d40e77
7
- data.tar.gz: 3940bed1a962c7ce3d7c71a2a52744317c51707a48c412973a8378ea351ec138e95834fce82481fdd9b3e49c34322539df55227dacd2f9f9713f31cd795c22ca
6
+ metadata.gz: bd56f181a60349d8dbfa029d5da3d6e2fd9746fbf1bbbb05b70745082af186ea2985c9928a659f9d9346ee8515f9b1e437bcd513c2845650da6b6c94d62cc2f0
7
+ data.tar.gz: bfa56fa807813ffe8dce4c3c8fd3d8e2d90587a9e14355fd9ea3d2b7a619fe16039145a87501748b96273145cff6f2186b4ae1fe04866406f489df5f9f7f5ef5
data/Gemfile.lock CHANGED
@@ -1,8 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- flow_object (0.1.2)
5
- mature_factory (~> 0.2.11)
4
+ flow_object (0.2.1)
5
+ mature_factory (~> 0.2.14)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
@@ -10,7 +10,7 @@ GEM
10
10
  coderay (1.1.3)
11
11
  diff-lcs (1.4.4)
12
12
  dry-inflector (0.1.2)
13
- mature_factory (0.2.11)
13
+ mature_factory (0.2.14)
14
14
  dry-inflector (~> 0.1)
15
15
  simple_facade (~> 0.2)
16
16
  method_source (1.0.0)
data/flow_object.gemspec CHANGED
@@ -36,7 +36,7 @@ Gem::Specification.new do |spec|
36
36
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
37
37
  spec.require_paths = ['lib']
38
38
 
39
- spec.add_dependency 'mature_factory', '~> 0.2.11'
39
+ spec.add_dependency 'mature_factory', '~> 0.2.14'
40
40
 
41
41
  spec.add_development_dependency 'bundler', '~> 1.17'
42
42
  spec.add_development_dependency 'pry'
data/lib/flow_object.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  require 'mature_factory'
2
+ require 'flow_object/callbacks'
3
+ require 'flow_object/runner'
2
4
  require 'flow_object/base'
3
5
  require 'flow_object/version'
4
6
 
@@ -3,109 +3,138 @@ module FlowObject
3
3
  include MatureFactory
4
4
  include MatureFactory::Features::Assemble
5
5
 
6
- composed_of :stages, :inputs, :outputs
6
+ produces :stages, :inputs, :outputs
7
7
 
8
8
  class << self
9
- attr_accessor :in, :out, :initial_values
9
+ extend Forwardable
10
+ attr_reader :in, :out, :initial_values
11
+ def_delegators :callbacks, :after_input_initialize, :after_flow_initialize,
12
+ :after_input_check, :after_flow_check, :after_output_initialize
10
13
  end
11
14
 
12
- attr_reader :output, :given
15
+ attr_reader :output
13
16
 
14
- def initialize(given)
15
- @given = given
16
- @output = self.class.__fo_wrap_output__
17
+ def initialize(flow, step_name = :flow)
18
+ @output = self.class.send(:__fo_wrap_output__)
19
+ self.class.link_with_delegation(@output, flow, step_name, true)
20
+ self.class.after_output_initialize.call(@output)
17
21
  end
18
22
 
19
- def inherited(subclass)
20
- subclass.from(self.in)
21
- subclass.to(self.out)
23
+ def on_failure(failed_step = nil)
24
+ # NOOP
22
25
  end
23
26
 
24
- def self.from(input)
25
- self.in = input
26
- self
27
+ def on_success
28
+ # NOOP
27
29
  end
28
30
 
29
- def self.to(output)
30
- self.out = output
31
- self
32
- end
31
+ module ClassMethods
32
+ def inherited(subclass)
33
+ super
34
+ subclass.from(self.in)
35
+ subclass.to(self.out)
36
+ subclass.after_input_initialize(&self.after_input_initialize)
37
+ subclass.after_flow_initialize(&self.after_flow_initialize)
38
+ subclass.after_input_check(&self.after_input_check)
39
+ subclass.after_flow_check(&self.after_flow_check)
40
+ subclass.after_output_initialize(&self.after_output_initialize)
41
+ end
33
42
 
34
- def self.__fo_wrap_input__
35
- return initial_values if self.in.nil?
36
- input_class = public_send(:"#{self.in}_input_class")
37
- return initial_values if input_class.nil?
38
- public_send(:"new_#{self.in}_input_instance", *initial_values)
39
- end
43
+ def callbacks
44
+ @callbacks ||= Callbacks.new
45
+ end
40
46
 
41
- def self.__fo_wrap_output__
42
- # rescue NoMethodError => ex
43
- # "You have not define output class. Please add `output :#{self.out}`"
44
- return if self.out.nil?
45
- return unless self.respond_to?(:"#{self.out}_output_class")
46
- output_class = public_send(:"#{self.out}_output_class")
47
- return if output_class.nil?
48
- public_send(:"new_#{self.out}_output_instance")
49
- end
47
+ def from(input)
48
+ @in = input
49
+ self
50
+ end
50
51
 
51
- def self.accept(*values)
52
- self.initial_values = values
53
- self
54
- end
52
+ def to(output)
53
+ @out = output
54
+ self
55
+ end
55
56
 
56
- def self.__fo_resolve_cascade__(cascade, step, failure)
57
- new(cascade).tap do |flow|
58
- if failure
59
- __fo_notify_error__(flow, step)
60
- else
61
- __fo_notify_success__(flow)
62
- end
57
+ def accept(*values)
58
+ @initial_values = values
59
+ self
63
60
  end
64
- end
65
61
 
66
- def self.__fo_notify_error__(flow, step)
67
- if flow.output.respond_to?(:"on_#{step}_failure")
68
- flow.output.public_send(:"on_#{step}_failure", flow.given)
69
- elsif flow.output.respond_to?(:on_failure)
70
- flow.output.on_failure(flow.given, step)
71
- elsif flow.respond_to?(:"on_#{step}_failure")
72
- flow.public_send(:"on_#{step}_failure")
73
- else
74
- flow.on_failure(step)
62
+ def call(flow: :main)
63
+ __fo_resolve__(__fo_process__(flow: flow))
75
64
  end
76
- end
77
65
 
78
- def self.__fo_notify_success__(flow)
79
- if flow.output.respond_to?(:on_success)
80
- flow.output.on_success(flow.given)
81
- else
82
- flow.on_success
66
+ def flow(name = :main, &block)
67
+ wrap(name, delegate: true, &block)
83
68
  end
84
- end
85
69
 
86
- def self.call(flow: :main)
87
- failure, previous_step, object = false, self.in, __fo_wrap_input__
88
- plan = public_send(:"build_#{flow}", previous_step, object)
89
- cascade = plan.call do |object, id|
90
- previous_step = id.to_sym
91
- if !object.valid?
92
- failure = true
93
- throw :halt
94
- end
95
- end
96
- __fo_resolve_cascade__(cascade, previous_step, failure)
97
- end
70
+ def link_with_delegation(target, object, accessor, delegate)
71
+ MatureFactory::Features::Assemble::AbstractBuilder
72
+ .link_with_delegation(target, object, accessor, delegate)
73
+ end
98
74
 
99
- def self.flow(name = 'main', &block)
100
- wrap(name, delegate: true, &block)
101
- end
75
+ private
102
76
 
103
- def on_failure(failed_step = nil)
104
- # NOOP
105
- end
77
+ def halt_flow?(object, id)
78
+ false
79
+ end
106
80
 
107
- def on_success
108
- # NOOP
81
+ def __fo_process__(flow: :main)
82
+ plan = __fo_build_flow__(flow, self.in, :input, __fo_wrap_input__)
83
+ Runner.new(plan, callbacks, method(:halt_flow?)).execute_plan
84
+ end
85
+
86
+ def __fo_build_flow__(flow, step_name, group, object)
87
+ public_send(:"build_#{flow}", title: step_name, group: group, object: object)
88
+ end
89
+
90
+ def __fo_wrap_input__
91
+ return initial_values if self.in.nil?
92
+ input_class = public_send(:"#{self.in}_input_class")
93
+ return initial_values if input_class.nil?
94
+ public_send(:"new_#{self.in}_input_instance", *initial_values)
95
+ end
96
+
97
+ def __fo_wrap_output__
98
+ # rescue NoMethodError => ex
99
+ # "You have not define output class. Please add `output :#{self.out}`"
100
+ return if self.out.nil?
101
+ return unless self.respond_to?(:"#{self.out}_output_class")
102
+ output_class = public_send(:"#{self.out}_output_class")
103
+ return if output_class.nil?
104
+ public_send(:"new_#{self.out}_output_instance")
105
+ end
106
+
107
+ def __fo_resolve__(runner)
108
+ new(runner.flow, runner.step_name).tap do |handler|
109
+ if runner.failure
110
+ __fo_notify_error__(handler, runner.step_name)
111
+ else
112
+ __fo_notify_success__(handler)
113
+ end
114
+ end
115
+ end
116
+
117
+ def __fo_notify_error__(handler, step)
118
+ if handler.output.respond_to?(:"on_#{step}_failure")
119
+ handler.output.public_send(:"on_#{step}_failure")
120
+ elsif handler.output.respond_to?(:on_failure)
121
+ handler.output.on_failure(step)
122
+ elsif handler.respond_to?(:"on_#{step}_failure")
123
+ handler.public_send(:"on_#{step}_failure")
124
+ else
125
+ handler.on_failure(step)
126
+ end
127
+ end
128
+
129
+ def __fo_notify_success__(handler)
130
+ if handler.output.respond_to?(:on_success)
131
+ handler.output.on_success
132
+ else
133
+ handler.on_success
134
+ end
135
+ end
109
136
  end
137
+
138
+ extend ClassMethods
110
139
  end
111
140
  end
@@ -0,0 +1,29 @@
1
+ module FlowObject
2
+ class Callbacks
3
+ SUPPORTED = %i[
4
+ after_input_initialize
5
+ after_flow_initialize
6
+ after_input_check
7
+ after_flow_check
8
+ after_output_initialize
9
+ ].freeze
10
+
11
+ NOOP = proc {}.freeze
12
+
13
+ def initialize
14
+ @callbacks = Hash.new { |hash, key| hash[key] = NOOP }
15
+ end
16
+
17
+ def method_missing(name, *_attrs, &block)
18
+ if SUPPORTED.include?(name)
19
+ block_given? ? @callbacks[name] = block : @callbacks[name]
20
+ else
21
+ super
22
+ end
23
+ end
24
+
25
+ def respond_to_missing?(name, *)
26
+ SUPPORTED.include?(name)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,67 @@
1
+ module FlowObject
2
+ class Runner
3
+ attr_reader :step_name, :failure, :flow
4
+
5
+ def initialize(plan, callbacks, halt_if_proc)
6
+ @plan = plan
7
+ @flow = flow
8
+ @failure = false
9
+ @step_name = nil
10
+ @callbacks = callbacks
11
+ @step_index = 0
12
+ @halt_if_proc = halt_if_proc
13
+ end
14
+
15
+ def execute_plan
16
+ @flow = call_flow_builder
17
+ after_flow_check(flow.public_send(@step_name))
18
+ self
19
+ end
20
+
21
+ private
22
+
23
+ def call_flow_builder
24
+ @plan.call do |object, id|
25
+ handle_step(object, id) { throw :halt }
26
+ end
27
+ end
28
+
29
+ def after_flow_check(object)
30
+ @callbacks.after_flow_check.call(object)
31
+ end
32
+
33
+ def after_input_initialize(object)
34
+ @callbacks.after_input_initialize.call(object)
35
+ end
36
+
37
+ def after_flow_initialize(object)
38
+ @callbacks.after_flow_initialize.call(object)
39
+ end
40
+
41
+ def after_input_check(object)
42
+ @callbacks.after_input_check.call(object)
43
+ end
44
+
45
+ def second_step?
46
+ @step_index == 1
47
+ end
48
+
49
+ def input_step?(id)
50
+ id.group == :input
51
+ end
52
+
53
+ def flow_step?(id)
54
+ id.group == :stage
55
+ end
56
+
57
+ def handle_step(object, id)
58
+ after_input_initialize(object) if input_step?(id)
59
+ after_flow_initialize(object) if second_step? && flow_step?(id)
60
+ @step_name = id.title
61
+ @step_index += 1
62
+ yield if @failure = @halt_if_proc.call(object, id)
63
+ after_input_check(object) if input_step?(id)
64
+ end
65
+
66
+ end
67
+ end
@@ -1,3 +1,3 @@
1
1
  module FlowObject
2
- VERSION = '0.1.2'.freeze
2
+ VERSION = '0.2.1'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flow_object
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrii Baran
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-01-08 00:00:00.000000000 Z
11
+ date: 2021-03-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mature_factory
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.2.11
19
+ version: 0.2.14
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.2.11
26
+ version: 0.2.14
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -116,6 +116,8 @@ files:
116
116
  - flow_object.gemspec
117
117
  - lib/flow_object.rb
118
118
  - lib/flow_object/base.rb
119
+ - lib/flow_object/callbacks.rb
120
+ - lib/flow_object/runner.rb
119
121
  - lib/flow_object/version.rb
120
122
  homepage: https://github.com/andriy-baran/flow_object
121
123
  licenses: