flow_object 0.1.4 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: ffa8dd6903e47060958b6623ed8a8c6b96074130
4
- data.tar.gz: 8d7772615968378288dc52f32a83eeb6bfb14db2
2
+ SHA256:
3
+ metadata.gz: cdecba76df1dc39202b7abcd32a626738447dc90ae0fc1d7cae695ca2aae876e
4
+ data.tar.gz: a6e4763933194dd419837ab96b75b22bc1e61b31473f6ccee3be052f2ac98e49
5
5
  SHA512:
6
- metadata.gz: 57215e81d52180ee8d28600be3ae0326834106e270e7c2fc00838fcd067ec5666ab21bc2696128a735e79d1a6ee1ea74dca46fa91de98d324b249bee8572d162
7
- data.tar.gz: fc71295067cbc45c298aea3fa0452f6e431ca02ed1ccbc5f370064b8fffc302fee14e66ae7d1b2a0fd63eaca9bd23aaa5dc351b2e93abf6122ae8e3850bc9600
6
+ metadata.gz: 11fe476ab5eb07624fb4629f520ee88a75b2da05e4393b72907247f84b3a569af961b1bcef5be91a86f47f03f6ebe639d305e6d2a7d80735efe9096e7a82a926
7
+ data.tar.gz: a1ae38390b9c66abb5f2a1df631eb3391b16563e5c7db1bae885802a93c50d272fa0b7388b8a2896f41fa0d924fba2b891a20bc51482168f028067c469fb222f
data/Gemfile.lock CHANGED
@@ -1,8 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- flow_object (0.1.4)
5
- mature_factory (~> 0.2.12)
4
+ flow_object (0.2.3)
5
+ mature_factory (~> 0.2.17)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
@@ -10,9 +10,8 @@ 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.12)
13
+ mature_factory (0.2.17)
14
14
  dry-inflector (~> 0.1)
15
- simple_facade (~> 0.2)
16
15
  method_source (1.0.0)
17
16
  pry (0.13.1)
18
17
  coderay (~> 1.1)
@@ -33,7 +32,6 @@ GEM
33
32
  rspec-support (3.9.3)
34
33
  rspec_vars_helper (0.1.0)
35
34
  rspec (>= 2.4)
36
- simple_facade (0.2.1)
37
35
 
38
36
  PLATFORMS
39
37
  ruby
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.12'
39
+ spec.add_dependency 'mature_factory', '~> 0.2.17'
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,110 +3,158 @@ 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 self.inherited(subclass)
20
- super
21
- subclass.from(self.in)
22
- subclass.to(self.out)
23
+ def on_exception(exception = nil)
24
+ # NOOP
23
25
  end
24
26
 
25
- def self.from(input)
26
- self.in = input
27
- self
27
+ def on_failure(failed_step = nil)
28
+ # NOOP
28
29
  end
29
30
 
30
- def self.to(output)
31
- self.out = output
32
- self
31
+ def on_success
32
+ # NOOP
33
33
  end
34
34
 
35
- def self.__fo_wrap_input__
36
- return initial_values if self.in.nil?
37
- input_class = public_send(:"#{self.in}_input_class")
38
- return initial_values if input_class.nil?
39
- public_send(:"new_#{self.in}_input_instance", *initial_values)
40
- end
35
+ module ClassMethods
36
+ def inherited(subclass)
37
+ super
38
+ subclass.from(self.in)
39
+ subclass.to(self.out)
40
+ subclass.after_input_initialize(&self.after_input_initialize)
41
+ subclass.after_flow_initialize(&self.after_flow_initialize)
42
+ subclass.after_input_check(&self.after_input_check)
43
+ subclass.after_flow_check(&self.after_flow_check)
44
+ subclass.after_output_initialize(&self.after_output_initialize)
45
+ end
41
46
 
42
- def self.__fo_wrap_output__
43
- # rescue NoMethodError => ex
44
- # "You have not define output class. Please add `output :#{self.out}`"
45
- return if self.out.nil?
46
- return unless self.respond_to?(:"#{self.out}_output_class")
47
- output_class = public_send(:"#{self.out}_output_class")
48
- return if output_class.nil?
49
- public_send(:"new_#{self.out}_output_instance")
50
- end
47
+ def callbacks
48
+ @callbacks ||= Callbacks.new
49
+ end
51
50
 
52
- def self.accept(*values)
53
- self.initial_values = values
54
- self
55
- end
51
+ def from(input)
52
+ @in = input
53
+ self
54
+ end
56
55
 
57
- def self.__fo_resolve_cascade__(cascade, step, failure)
58
- new(cascade).tap do |flow|
59
- if failure
60
- __fo_notify_error__(flow, step)
61
- else
62
- __fo_notify_success__(flow)
63
- end
56
+ def to(output)
57
+ @out = output
58
+ self
64
59
  end
65
- end
66
60
 
67
- def self.__fo_notify_error__(flow, step)
68
- if flow.output.respond_to?(:"on_#{step}_failure")
69
- flow.output.public_send(:"on_#{step}_failure", flow.given)
70
- elsif flow.output.respond_to?(:on_failure)
71
- flow.output.on_failure(flow.given, step)
72
- elsif flow.respond_to?(:"on_#{step}_failure")
73
- flow.public_send(:"on_#{step}_failure")
74
- else
75
- flow.on_failure(step)
61
+ def accept(*values)
62
+ @initial_values = values
63
+ self
76
64
  end
77
- end
78
65
 
79
- def self.__fo_notify_success__(flow)
80
- if flow.output.respond_to?(:on_success)
81
- flow.output.on_success(flow.given)
82
- else
83
- flow.on_success
66
+ def call(flow: :main)
67
+ __fo_resolve__(__fo_process__(flow: flow))
84
68
  end
85
- end
86
69
 
87
- def self.call(flow: :main)
88
- failure, previous_step, object = false, :"#{self.in}_input", __fo_wrap_input__
89
- plan = public_send(:"build_#{flow}", previous_step, object)
90
- cascade = plan.call do |object, id|
91
- previous_step = id.to_sym
92
- if !object.valid?
93
- failure = true
94
- throw :halt
95
- end
96
- end
97
- __fo_resolve_cascade__(cascade, previous_step, failure)
98
- end
70
+ def flow(name = :main, &block)
71
+ wrap(name, delegate: true, on_exception: :halt, &block)
72
+ end
99
73
 
100
- def self.flow(name = 'main', &block)
101
- wrap(name, delegate: true, &block)
102
- end
74
+ def link_with_delegation(target, object, accessor, delegate)
75
+ MatureFactory::Features::Assemble::AbstractBuilder
76
+ .link_with_delegation(target, object, accessor, delegate)
77
+ end
103
78
 
104
- def on_failure(failed_step = nil)
105
- # NOOP
106
- end
79
+ private
107
80
 
108
- def on_success
109
- # NOOP
81
+ def halt_flow?(object, id)
82
+ false
83
+ end
84
+
85
+ def __fo_process__(flow: :main)
86
+ plan = __fo_build_flow__(flow, self.in, :input, __fo_wrap_input__)
87
+ Runner.new(plan, callbacks, method(:halt_flow?)).execute_plan
88
+ end
89
+
90
+ def __fo_build_flow__(flow, step_name, group, object)
91
+ public_send(:"build_#{flow}", title: step_name, group: group, object: object)
92
+ end
93
+
94
+ def __fo_wrap_input__
95
+ return initial_values if self.in.nil?
96
+ input_class = public_send(:"#{self.in}_input_class")
97
+ return initial_values if input_class.nil?
98
+ public_send(:"new_#{self.in}_input_instance", *initial_values)
99
+ end
100
+
101
+ def __fo_wrap_output__
102
+ # rescue NoMethodError => ex
103
+ # "You have not define output class. Please add `output :#{self.out}`"
104
+ return if self.out.nil?
105
+ return unless self.respond_to?(:"#{self.out}_output_class")
106
+ output_class = public_send(:"#{self.out}_output_class")
107
+ return if output_class.nil?
108
+ public_send(:"new_#{self.out}_output_instance")
109
+ end
110
+
111
+ def __fo_resolve__(runner)
112
+ new(runner.flow.public_send(runner.step_name), runner.step_name).tap do |handler|
113
+ if runner.flow.exceptional?
114
+ __fo_notify_exception__(handler, runner.flow.exception)
115
+ elsif runner.failure
116
+ __fo_notify_error__(handler, runner.step_name)
117
+ else
118
+ __fo_notify_success__(handler)
119
+ end
120
+ end
121
+ end
122
+
123
+ def __fo_notify_exception__(handler, exception)
124
+ step = exception.step_id.title
125
+ if handler.output.respond_to?(:"on_#{step}_exception")
126
+ handler.output.public_send(:"on_#{step}_exception", exception)
127
+ elsif handler.output.respond_to?(:on_exception)
128
+ handler.output.on_exception(exception)
129
+ elsif handler.respond_to?(:"on_#{step}_exception")
130
+ handler.public_send(:"on_#{step}_exception", exception)
131
+ else
132
+ handler.on_exception(exception)
133
+ end
134
+ __fo_notify_error__(handler, exception.step_id.title)
135
+ end
136
+
137
+ def __fo_notify_error__(handler, step)
138
+ if handler.output.respond_to?(:"on_#{step}_failure")
139
+ handler.output.public_send(:"on_#{step}_failure")
140
+ elsif handler.output.respond_to?(:on_failure)
141
+ handler.output.on_failure(step)
142
+ elsif handler.respond_to?(:"on_#{step}_failure")
143
+ handler.public_send(:"on_#{step}_failure")
144
+ else
145
+ handler.on_failure(step)
146
+ end
147
+ end
148
+
149
+ def __fo_notify_success__(handler)
150
+ if handler.output.respond_to?(:on_success)
151
+ handler.output.on_success
152
+ else
153
+ handler.on_success
154
+ end
155
+ end
110
156
  end
157
+
158
+ extend ClassMethods
111
159
  end
112
160
  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.4'.freeze
2
+ VERSION = '0.2.3'.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.4
4
+ version: 0.2.3
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-04-23 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.12
19
+ version: 0.2.17
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.12
26
+ version: 0.2.17
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:
@@ -139,8 +141,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
139
141
  - !ruby/object:Gem::Version
140
142
  version: '0'
141
143
  requirements: []
142
- rubyforge_project:
143
- rubygems_version: 2.5.1
144
+ rubygems_version: 3.2.16
144
145
  signing_key:
145
146
  specification_version: 4
146
147
  summary: Create objects for storing application flows