workflow_template 0.0.4
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 +7 -0
- data/lib/workflow_template/action/abstract.rb +40 -0
- data/lib/workflow_template/action/description/validated.rb +58 -0
- data/lib/workflow_template/action/description/wrapper.rb +28 -0
- data/lib/workflow_template/action/nested.rb +59 -0
- data/lib/workflow_template/action/simple.rb +28 -0
- data/lib/workflow_template/action/validated.rb +104 -0
- data/lib/workflow_template/action/wrapper.rb +32 -0
- data/lib/workflow_template/action.rb +20 -0
- data/lib/workflow_template/adapters/state/default.rb +72 -0
- data/lib/workflow_template/adapters/state/dry_monads.rb +70 -0
- data/lib/workflow_template/adapters/validation/active_model/builder.rb +18 -0
- data/lib/workflow_template/adapters/validation/active_model/failure.rb +17 -0
- data/lib/workflow_template/adapters/validation/active_model/null_model.rb +24 -0
- data/lib/workflow_template/adapters/validation/active_model/validator.rb +35 -0
- data/lib/workflow_template/adapters/validation/active_model.rb +24 -0
- data/lib/workflow_template/adapters/validation/dry_validation/builder.rb +18 -0
- data/lib/workflow_template/adapters/validation/dry_validation/failure.rb +19 -0
- data/lib/workflow_template/adapters/validation/dry_validation/validator.rb +46 -0
- data/lib/workflow_template/adapters/validation/dry_validation.rb +24 -0
- data/lib/workflow_template/adapters/validation/generic/block.rb +24 -0
- data/lib/workflow_template/adapters/validation/generic/builder.rb +28 -0
- data/lib/workflow_template/adapters/validation/generic/object.rb +30 -0
- data/lib/workflow_template/adapters/validation/generic/validator.rb +25 -0
- data/lib/workflow_template/adapters/validation/generic.rb +24 -0
- data/lib/workflow_template/definer/has_actions/actions.rb +90 -0
- data/lib/workflow_template/definer/has_actions/description.rb +48 -0
- data/lib/workflow_template/definer/has_actions/dsl.rb +64 -0
- data/lib/workflow_template/definer/has_actions/insert.rb +28 -0
- data/lib/workflow_template/definer/has_actions/inside.rb +27 -0
- data/lib/workflow_template/definer/has_actions/nested.rb +65 -0
- data/lib/workflow_template/definer/has_actions/position.rb +83 -0
- data/lib/workflow_template/definer/has_actions/redefine.rb +28 -0
- data/lib/workflow_template/definer/has_actions/root.rb +22 -0
- data/lib/workflow_template/definer/has_actions.rb +45 -0
- data/lib/workflow_template/definer/has_default_state_transition_strategy.rb +34 -0
- data/lib/workflow_template/definer/has_output_normalizer.rb +35 -0
- data/lib/workflow_template/definer/has_state_adapter.rb +30 -0
- data/lib/workflow_template/definer/has_validations/action.rb +20 -0
- data/lib/workflow_template/definer/has_validations/description.rb +38 -0
- data/lib/workflow_template/definer/has_validations/validations.rb +162 -0
- data/lib/workflow_template/definer/has_validations.rb +70 -0
- data/lib/workflow_template/error.rb +99 -0
- data/lib/workflow_template/outcome/block.rb +58 -0
- data/lib/workflow_template/outcome/handler.rb +106 -0
- data/lib/workflow_template/outcome/status.rb +33 -0
- data/lib/workflow_template/outcome/statuses.rb +60 -0
- data/lib/workflow_template/outcome.rb +53 -0
- data/lib/workflow_template/performer.rb +46 -0
- data/lib/workflow_template/state/abstract.rb +33 -0
- data/lib/workflow_template/state/adapter.rb +67 -0
- data/lib/workflow_template/state/class_methods.rb +43 -0
- data/lib/workflow_template/state/final.rb +74 -0
- data/lib/workflow_template/state/intermediate.rb +102 -0
- data/lib/workflow_template/state/meta.rb +35 -0
- data/lib/workflow_template/state/normalizer.rb +34 -0
- data/lib/workflow_template/state/validation.rb +32 -0
- data/lib/workflow_template/state.rb +41 -0
- data/lib/workflow_template/validation/adapter/abstract/builder.rb +28 -0
- data/lib/workflow_template/validation/adapter/abstract/result/failure.rb +25 -0
- data/lib/workflow_template/validation/adapter/abstract/validator.rb +23 -0
- data/lib/workflow_template/validation/adapter.rb +35 -0
- data/lib/workflow_template/validation/builder/error.rb +11 -0
- data/lib/workflow_template/validation/builder/proxy.rb +129 -0
- data/lib/workflow_template/validation/error.rb +16 -0
- data/lib/workflow_template/validation/evaluation/abstract.rb +57 -0
- data/lib/workflow_template/validation/evaluation/boolean.rb +28 -0
- data/lib/workflow_template/validation/evaluation/canonical.rb +21 -0
- data/lib/workflow_template/validation/evaluation.rb +4 -0
- data/lib/workflow_template/validation/result/failure/abstract.rb +15 -0
- data/lib/workflow_template/validation/result/failure.rb +52 -0
- data/lib/workflow_template/validation/result/success.rb +19 -0
- data/lib/workflow_template/validation/validator/result/failure.rb +36 -0
- data/lib/workflow_template/validation/validator/result/success.rb +21 -0
- data/lib/workflow_template/workflow/description.rb +56 -0
- data/lib/workflow_template/workflow.rb +69 -0
- data/lib/workflow_template.rb +11 -0
- metadata +126 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../../../validation/adapter/abstract/validator'
|
|
4
|
+
require_relative '../../../validation/validator/result/success'
|
|
5
|
+
require_relative 'failure'
|
|
6
|
+
|
|
7
|
+
module WorkflowTemplate
|
|
8
|
+
module Adapters
|
|
9
|
+
module Validation
|
|
10
|
+
module DryValidation
|
|
11
|
+
class Validator
|
|
12
|
+
extend WorkflowTemplate::Validation::Adapter::Abstract::Validator
|
|
13
|
+
|
|
14
|
+
def initialize(contract_class)
|
|
15
|
+
@contract_class = contract_class
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def call(input, context: {})
|
|
19
|
+
return Failure.new(self, code: :input_null) if input.nil?
|
|
20
|
+
|
|
21
|
+
result = contract(context).call(input)
|
|
22
|
+
return WorkflowTemplate::Validation::Validator::Result::Success if result.success?
|
|
23
|
+
|
|
24
|
+
Failure.new(
|
|
25
|
+
self,
|
|
26
|
+
code: :input_invalid,
|
|
27
|
+
data: result
|
|
28
|
+
)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def describe
|
|
32
|
+
'contract to be satisfied'
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
attr_reader :contract_class
|
|
38
|
+
|
|
39
|
+
def contract(context)
|
|
40
|
+
contract_class.new(**context)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../../validation/adapter'
|
|
4
|
+
require_relative 'dry_validation/builder'
|
|
5
|
+
|
|
6
|
+
module WorkflowTemplate
|
|
7
|
+
module Adapters
|
|
8
|
+
module Validation
|
|
9
|
+
module DryValidation
|
|
10
|
+
extend WorkflowTemplate::Validation::Adapter
|
|
11
|
+
|
|
12
|
+
def self.builder_class
|
|
13
|
+
Builder
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.result_type
|
|
17
|
+
:canonical
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
register(:dry_validation)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'validator'
|
|
4
|
+
|
|
5
|
+
module WorkflowTemplate
|
|
6
|
+
module Adapters
|
|
7
|
+
module Validation
|
|
8
|
+
module Generic
|
|
9
|
+
class Block < Validator
|
|
10
|
+
def initialize(block)
|
|
11
|
+
@block = block
|
|
12
|
+
super()
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def call_foreign(object, **opts)
|
|
18
|
+
@block.call(object, **opts)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../../../validation/adapter/abstract/builder'
|
|
4
|
+
require_relative 'object'
|
|
5
|
+
require_relative 'block'
|
|
6
|
+
|
|
7
|
+
module WorkflowTemplate
|
|
8
|
+
module Adapters
|
|
9
|
+
module Validation
|
|
10
|
+
module Generic
|
|
11
|
+
class Builder < WorkflowTemplate::Validation::Adapter::Abstract::Builder
|
|
12
|
+
class Error < WorkflowTemplate::Error; end
|
|
13
|
+
|
|
14
|
+
def validate(&block)
|
|
15
|
+
return self unless block
|
|
16
|
+
|
|
17
|
+
proxy.declare(Generic::Block.new(block))
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def using(implementation)
|
|
21
|
+
validator = Generic::Object.new(implementation)
|
|
22
|
+
proxy.declare(validator)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'validator'
|
|
4
|
+
|
|
5
|
+
module WorkflowTemplate
|
|
6
|
+
module Adapters
|
|
7
|
+
module Validation
|
|
8
|
+
module Generic
|
|
9
|
+
class Object < Validator
|
|
10
|
+
def initialize(object)
|
|
11
|
+
@object = object
|
|
12
|
+
super()
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def describe
|
|
16
|
+
object.respond_to?(:describe) ? object.describe : super
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
attr_reader :object
|
|
22
|
+
|
|
23
|
+
def call_foreign(value, **opts)
|
|
24
|
+
object.call(value, **opts)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../../../validation/adapter/abstract/validator'
|
|
4
|
+
|
|
5
|
+
module WorkflowTemplate
|
|
6
|
+
module Adapters
|
|
7
|
+
module Validation
|
|
8
|
+
module Generic
|
|
9
|
+
class Validator
|
|
10
|
+
include WorkflowTemplate::Validation::Adapter::Abstract::Validator
|
|
11
|
+
|
|
12
|
+
def call(object, **opts)
|
|
13
|
+
call_foreign(object, **opts)
|
|
14
|
+
rescue StandardError => e
|
|
15
|
+
raise Fatal::ForeignCodeError, e
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def describe
|
|
19
|
+
"#{self.class.name.split('::').last.downcase} validation"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../../validation/adapter'
|
|
4
|
+
require_relative 'generic/builder'
|
|
5
|
+
|
|
6
|
+
module WorkflowTemplate
|
|
7
|
+
module Adapters
|
|
8
|
+
module Validation
|
|
9
|
+
module Generic
|
|
10
|
+
extend WorkflowTemplate::Validation::Adapter
|
|
11
|
+
|
|
12
|
+
def self.builder_class
|
|
13
|
+
Builder
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.result_type
|
|
17
|
+
:boolean
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
register(:generic)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../../error'
|
|
4
|
+
|
|
5
|
+
module WorkflowTemplate
|
|
6
|
+
module Definer
|
|
7
|
+
module HasActions
|
|
8
|
+
module Actions
|
|
9
|
+
class Unprepared
|
|
10
|
+
def self.instance
|
|
11
|
+
new
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def initialize(simple: [], wrapper: [])
|
|
15
|
+
@unprepared_simple = simple.freeze
|
|
16
|
+
@unprepared_wrapper = wrapper.freeze
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private_class_method :new
|
|
20
|
+
|
|
21
|
+
def add_simple(action, position)
|
|
22
|
+
@unprepared_simple = [*@unprepared_simple, [action, position]].freeze
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def add_wrapper(action)
|
|
26
|
+
@unprepared_wrapper = [action, *@unprepared_wrapper].freeze
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def prepared
|
|
30
|
+
simple = prepare_simple(existing: [])
|
|
31
|
+
wrapper = prepare_wrapper(existing: [])
|
|
32
|
+
|
|
33
|
+
Prepared.new(simple: simple, wrapper: wrapper)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
protected
|
|
37
|
+
|
|
38
|
+
attr_reader :unprepared_simple, :unprepared_wrapper
|
|
39
|
+
|
|
40
|
+
def prepare_simple(existing:)
|
|
41
|
+
unprepared_simple.reduce(existing) do |existing, (action, position)|
|
|
42
|
+
position.apply_onto(existing, action)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def prepare_wrapper(existing:)
|
|
47
|
+
unprepared_wrapper + existing
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
class Prepared
|
|
52
|
+
attr_reader :simple, :wrapper
|
|
53
|
+
|
|
54
|
+
def initialize(simple:, wrapper:)
|
|
55
|
+
@simple = simple.freeze
|
|
56
|
+
@wrapper = wrapper.freeze
|
|
57
|
+
freeze
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def merge(unprepared)
|
|
61
|
+
simple = unprepared.send(:prepare_simple, existing: self.simple)
|
|
62
|
+
wrapper = unprepared.send(:prepare_wrapper, existing: self.wrapper)
|
|
63
|
+
|
|
64
|
+
Prepared.new(simple: simple, wrapper: wrapper)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def map(&block)
|
|
68
|
+
simple_actions = simple.map(&block)
|
|
69
|
+
wrapper_actions = wrapper.map(&block)
|
|
70
|
+
self.class.new simple: simple_actions, wrapper: wrapper_actions
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def next_wrapper_action
|
|
74
|
+
return [nil, self] if wrapper.empty?
|
|
75
|
+
|
|
76
|
+
action, *rest = wrapper
|
|
77
|
+
container = self.class.new(simple: simple, wrapper: rest)
|
|
78
|
+
[action, container]
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def inspect
|
|
82
|
+
simple = simple().map(&:name).join(', ')
|
|
83
|
+
wrapper = wrapper().map(&:name).join(', ')
|
|
84
|
+
"#<#{self.class.name} simple=[#{simple}] wrapper=[#{wrapper}]>"
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../../workflow/description'
|
|
4
|
+
|
|
5
|
+
module WorkflowTemplate
|
|
6
|
+
module Definer
|
|
7
|
+
module HasActions
|
|
8
|
+
class Description
|
|
9
|
+
Workflow::Description.register(:perform, :actions) do |workflow|
|
|
10
|
+
Description.new(workflow)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
attr_reader :workflow
|
|
14
|
+
|
|
15
|
+
def initialize(workflow)
|
|
16
|
+
@workflow = workflow
|
|
17
|
+
freeze
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def format(level:)
|
|
21
|
+
self.class.describe(workflow).flat_map { |action| action.format(level: level) }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.describe(workflow)
|
|
25
|
+
describe_wrapper_actions(workflow.actions.wrapper, workflow.actions.simple)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.describe_wrapper_actions(wrapper_actions, simple_actions)
|
|
29
|
+
action, *rest = wrapper_actions
|
|
30
|
+
if action.nil?
|
|
31
|
+
describe_actions(simple_actions)
|
|
32
|
+
else
|
|
33
|
+
[describe_wrapper_action(action, rest, simple_actions)]
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def self.describe_wrapper_action(action, rest, simple_actions)
|
|
38
|
+
nested = describe_wrapper_actions(rest, simple_actions)
|
|
39
|
+
action.describe(nested)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def self.describe_actions(actions)
|
|
43
|
+
actions.map(&:describe)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../../action'
|
|
4
|
+
require_relative 'insert'
|
|
5
|
+
require_relative 'inside'
|
|
6
|
+
|
|
7
|
+
module WorkflowTemplate
|
|
8
|
+
module Definer
|
|
9
|
+
module HasActions
|
|
10
|
+
module Dsl
|
|
11
|
+
def apply(action_name, **opts, &block)
|
|
12
|
+
insert_action(action_name, position: :after, **opts, &block)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
alias and_then apply
|
|
16
|
+
|
|
17
|
+
def append_action(after: nil)
|
|
18
|
+
Insert.new(self, :after, after)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def prepend_action(before: nil)
|
|
22
|
+
Insert.new(self, :before, before)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def replace_action(name)
|
|
26
|
+
Insert.new(self, :at, name)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def inside_action(name, &block)
|
|
30
|
+
position = Inside.new(name, block)
|
|
31
|
+
store_action(nil, position)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def wrap_template(action_name, **opts)
|
|
35
|
+
action = Action.instance(action_name, :wrapper, **translate_action_parameters(**opts))
|
|
36
|
+
store_wrapper_action(action)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def remove_action(action_name)
|
|
40
|
+
position = Position.instance(:at, action_name)
|
|
41
|
+
store_action(nil, position)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
protected
|
|
45
|
+
|
|
46
|
+
def insert_action(action_name, position: :after, reference: nil, **opts, &block)
|
|
47
|
+
action = if block.nil?
|
|
48
|
+
Action.instance(action_name, :simple, **translate_action_parameters(**opts), &block)
|
|
49
|
+
else
|
|
50
|
+
wrapper_action = Action.instance(action_name, :wrapper, **translate_action_parameters(**opts))
|
|
51
|
+
Action::Nested::Unprepared.instance(wrapper_action, Nested::Unprepared, &block)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
position = Position.instance(position, reference)
|
|
55
|
+
store_action(action, position)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def translate_action_parameters(state: nil, validate: nil, **opts)
|
|
59
|
+
{ state_transition_strategy: state, validates: validate, **opts }
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module WorkflowTemplate
|
|
4
|
+
module Definer
|
|
5
|
+
module HasActions
|
|
6
|
+
class Insert
|
|
7
|
+
def initialize(workflow, position, reference)
|
|
8
|
+
@workflow = workflow
|
|
9
|
+
@position = position
|
|
10
|
+
@reference = reference
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def apply(action_name, **opts, &block)
|
|
14
|
+
@workflow.send(
|
|
15
|
+
:insert_action,
|
|
16
|
+
action_name,
|
|
17
|
+
position: @position,
|
|
18
|
+
reference: @reference,
|
|
19
|
+
**opts,
|
|
20
|
+
&block
|
|
21
|
+
)
|
|
22
|
+
@workflow = nil
|
|
23
|
+
nil
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'position'
|
|
4
|
+
|
|
5
|
+
module WorkflowTemplate
|
|
6
|
+
module Definer
|
|
7
|
+
module HasActions
|
|
8
|
+
class Inside
|
|
9
|
+
attr_reader :reference, :block
|
|
10
|
+
|
|
11
|
+
def initialize(reference, block)
|
|
12
|
+
@reference = reference
|
|
13
|
+
@block = block
|
|
14
|
+
freeze
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def apply_onto(actions, action)
|
|
18
|
+
raise Error, 'Action expected to be nil' unless action.nil?
|
|
19
|
+
|
|
20
|
+
before, action, after = Position.slice_actions(actions, reference)
|
|
21
|
+
clone = action.duplicate(&block)
|
|
22
|
+
[*before, clone, *after]
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'redefine'
|
|
4
|
+
require_relative 'description'
|
|
5
|
+
require_relative 'dsl'
|
|
6
|
+
|
|
7
|
+
module WorkflowTemplate
|
|
8
|
+
module Definer
|
|
9
|
+
module HasActions
|
|
10
|
+
module Nested
|
|
11
|
+
include HasActions
|
|
12
|
+
|
|
13
|
+
def describe
|
|
14
|
+
raise Error, "Can't describe unfrozen workflow" unless frozen?
|
|
15
|
+
|
|
16
|
+
Description.new(self)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
module Unprepared
|
|
20
|
+
include Dsl
|
|
21
|
+
include Nested
|
|
22
|
+
include HasActions::Redefine
|
|
23
|
+
|
|
24
|
+
def prepare(*args)
|
|
25
|
+
unprepared = self
|
|
26
|
+
|
|
27
|
+
target = Module.new do
|
|
28
|
+
extend Prepared
|
|
29
|
+
|
|
30
|
+
define_singleton_method :unprepared do
|
|
31
|
+
unprepared
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
actions.wrapper.each do |action|
|
|
36
|
+
target.send :store_wrapper_action, action.prepare(*args)
|
|
37
|
+
end
|
|
38
|
+
actions.simple.each do |action|
|
|
39
|
+
position = Position.instance(:after, nil)
|
|
40
|
+
target.send :store_action, action.prepare(*args), position
|
|
41
|
+
end
|
|
42
|
+
target.freeze
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def redefine(&block)
|
|
46
|
+
redefine_onto(Unprepared, &block)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
module Prepared
|
|
51
|
+
include Nested
|
|
52
|
+
include Performer
|
|
53
|
+
|
|
54
|
+
def prepare(*args)
|
|
55
|
+
unprepared.prepare(*args)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def redefine(&block)
|
|
59
|
+
unprepared.redefine(&block)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../../error'
|
|
4
|
+
|
|
5
|
+
module WorkflowTemplate
|
|
6
|
+
module Definer
|
|
7
|
+
module HasActions
|
|
8
|
+
class Position
|
|
9
|
+
def self.instance(type, reference)
|
|
10
|
+
case type
|
|
11
|
+
when :before
|
|
12
|
+
Position::Before.new(reference)
|
|
13
|
+
when :after
|
|
14
|
+
Position::After.new(reference)
|
|
15
|
+
when :at
|
|
16
|
+
raise Error, 'Reference not expected to be nil' if reference.nil?
|
|
17
|
+
|
|
18
|
+
Position::At.new(reference)
|
|
19
|
+
else
|
|
20
|
+
raise Error, "Unexpected position: #{type}"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.slice_actions(actions, reference)
|
|
25
|
+
index, *rest = actions.each_index.reduce([]) do |result, index|
|
|
26
|
+
next result unless actions[index].name == reference
|
|
27
|
+
|
|
28
|
+
[*result, index]
|
|
29
|
+
end
|
|
30
|
+
raise Error, "Reference not found: #{reference}" if index.nil?
|
|
31
|
+
raise Error, "Duplicate action name: #{reference}" if rest.length.positive?
|
|
32
|
+
|
|
33
|
+
before = actions[0...index]
|
|
34
|
+
action = actions[index]
|
|
35
|
+
after = actions[(index + 1)..]
|
|
36
|
+
[before, action, after]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def initialize(reference)
|
|
40
|
+
@reference = reference&.to_sym
|
|
41
|
+
freeze
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def apply_onto(actions, action)
|
|
45
|
+
if reference.nil?
|
|
46
|
+
apply_without_reference(actions, action)
|
|
47
|
+
else
|
|
48
|
+
before, reference, after = self.class.slice_actions(actions, self.reference)
|
|
49
|
+
apply_with_reference(before, action, reference, after)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
attr_reader :reference
|
|
54
|
+
|
|
55
|
+
class Before < Position
|
|
56
|
+
def apply_without_reference(actions, action)
|
|
57
|
+
[action, *actions]
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def apply_with_reference(before, action, reference, after)
|
|
61
|
+
[*before, action, reference, *after]
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
class After < Position
|
|
66
|
+
def apply_without_reference(actions, action)
|
|
67
|
+
[*actions, action]
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def apply_with_reference(before, action, reference, after)
|
|
71
|
+
[*before, reference, action, *after]
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
class At < Position
|
|
76
|
+
def apply_with_reference(before, action, _reference, after)
|
|
77
|
+
action.nil? ? [*before, *after] : [*before, action, *after]
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'position'
|
|
4
|
+
|
|
5
|
+
module WorkflowTemplate
|
|
6
|
+
module Definer
|
|
7
|
+
module HasActions
|
|
8
|
+
module Redefine
|
|
9
|
+
def redefine_onto(workflow_module, &block)
|
|
10
|
+
target = Module.new do
|
|
11
|
+
extend workflow_module
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
actions.wrapper.each do |action|
|
|
15
|
+
target.send :store_wrapper_action, action
|
|
16
|
+
end
|
|
17
|
+
actions.simple.each do |action|
|
|
18
|
+
position = Position.instance(:after, nil)
|
|
19
|
+
target.send :store_action, action, position
|
|
20
|
+
end
|
|
21
|
+
target.instance_eval(&block)
|
|
22
|
+
|
|
23
|
+
target.freeze
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'dsl'
|
|
4
|
+
|
|
5
|
+
module WorkflowTemplate
|
|
6
|
+
module Definer
|
|
7
|
+
module HasActions
|
|
8
|
+
module Root
|
|
9
|
+
include HasActions
|
|
10
|
+
include Dsl
|
|
11
|
+
|
|
12
|
+
def prepare_actions
|
|
13
|
+
actions.map { prepare_action(_1) }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def prepare_action(action)
|
|
17
|
+
action
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|