flows 0.5.1 → 0.6.0
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 +4 -4
- data/.rubocop.yml +3 -1
- data/.rubocop_todo.yml +27 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +17 -1
- data/bin/benchmark_cli/examples/.rubocop.yml +3 -0
- data/bin/errors +10 -2
- data/bin/errors_cli/interface_error_demo.rb +17 -0
- data/flows.gemspec +2 -0
- data/lib/flows/contract.rb +2 -2
- data/lib/flows/contract/error.rb +1 -2
- data/lib/flows/plugin.rb +1 -0
- data/lib/flows/plugin/dependency_injector.rb +11 -0
- data/lib/flows/plugin/dependency_injector/dependency_list.rb +1 -3
- data/lib/flows/plugin/interface.rb +84 -0
- data/lib/flows/plugin/output_contract/dsl.rb +1 -1
- data/lib/flows/plugin/output_contract/errors.rb +1 -1
- data/lib/flows/plugin/profiler/report/flat/method_report.rb +1 -2
- data/lib/flows/plugin/profiler/report/tree/calculated_node.rb +1 -1
- data/lib/flows/plugin/profiler/report/tree/node.rb +1 -2
- data/lib/flows/railway/step.rb +7 -7
- data/lib/flows/shared_context_pipeline.rb +46 -3
- data/lib/flows/shared_context_pipeline/dsl/callbacks.rb +1 -4
- data/lib/flows/shared_context_pipeline/dsl/tracks.rb +4 -4
- data/lib/flows/shared_context_pipeline/mutation_step.rb +3 -2
- data/lib/flows/shared_context_pipeline/step.rb +15 -4
- data/lib/flows/shared_context_pipeline/track.rb +1 -1
- data/lib/flows/shared_context_pipeline/wrap.rb +1 -2
- data/lib/flows/util/inheritable_singleton_vars/dup_strategy.rb +8 -6
- data/lib/flows/util/prepend_to_class.rb +14 -2
- data/lib/flows/version.rb +1 -1
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dd10b19c7b749fd46c6b8897db3c9912603b4111af7793449d5ff49f69adfcb1
|
4
|
+
data.tar.gz: b18271b7321f199e978ebd4f66f2d21e532c20dd37cd61b6b641b00d875c2f4c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6b3e90d9b76911f1e0a0539bd89eee76a68dcba04f4136858412e4d0e0e1ca51ff8f35027963ef52fdd870f2b74ffe9a326aca4802cd443af2e55f8bf18f67b1
|
7
|
+
data.tar.gz: 5a6306a15a6024a1c9412f325ab3454b029abcd7d80defee6a9d5b286e8664981b572fb0ecf6f91d06b98c7d5f3040169fe02aae43b8ee8261fa7b65c469fe54
|
data/.rubocop.yml
CHANGED
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# This configuration was generated by
|
2
|
+
# `rubocop --auto-gen-config --auto-gen-only-exclude`
|
3
|
+
# on 2020-08-22 07:49:05 UTC using RuboCop version 0.89.1.
|
4
|
+
# The point is for the user to remove these configuration records
|
5
|
+
# one by one as the offenses are removed from the code base.
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
8
|
+
|
9
|
+
# Offense count: 27
|
10
|
+
#
|
11
|
+
# *** NON-GENERATED COMMENT ***
|
12
|
+
# I'm not sure about enabling this cop
|
13
|
+
# * using super may has performance impact
|
14
|
+
# * but for some cases it still can be useful
|
15
|
+
# Research needed
|
16
|
+
Lint/MissingSuper:
|
17
|
+
Enabled: false
|
18
|
+
|
19
|
+
# Offense count: 5
|
20
|
+
# Configuration parameters: AllowSubject, Max.
|
21
|
+
#
|
22
|
+
# *** NON-GENERATED COMMENT ***
|
23
|
+
# Might be it's impossible to satisfy this cop or significant refactoring of these tests needed
|
24
|
+
RSpec/MultipleMemoizedHelpers:
|
25
|
+
Exclude:
|
26
|
+
- 'spec/flows/flow/node_spec.rb'
|
27
|
+
- 'spec/flows/util/inheritable_singleton_vars/isolation_strategy_spec.rb'
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.6.
|
1
|
+
2.6.6
|
data/CHANGELOG.md
CHANGED
@@ -16,6 +16,21 @@ Types of changes:
|
|
16
16
|
|
17
17
|
## [Unreleased]
|
18
18
|
|
19
|
+
## [0.6.0] - 2020-09-23
|
20
|
+
|
21
|
+
### Added
|
22
|
+
|
23
|
+
* `Flows::Plugin::Interface` basic implementation
|
24
|
+
* `Flows::SharedContextPipeline` simple sub-pipelines injection
|
25
|
+
|
26
|
+
### Changed
|
27
|
+
|
28
|
+
* `Flows::SharedContextPipeline` callbacks execution method is changed to `instance_exec` (previously was `.call`)
|
29
|
+
|
30
|
+
### Fixed
|
31
|
+
|
32
|
+
* `Flows::Plugin::DependencyInjector` and modules generated by `Flows::Util::InheritableSingletonVars::DupStrategy` now can be safely included several times in the inheritance chain
|
33
|
+
|
19
34
|
## [0.5.1] - 2020-06-29
|
20
35
|
|
21
36
|
### Fixed
|
@@ -59,7 +74,8 @@ Types of changes:
|
|
59
74
|
* `Flows::Util::PrependToClass` - allows to prepend some module to class even if
|
60
75
|
target module did not included directly into class.
|
61
76
|
|
62
|
-
[unreleased]: https://github.com/ffloyd/flows/compare/v0.
|
77
|
+
[unreleased]: https://github.com/ffloyd/flows/compare/v0.6.0...HEAD
|
78
|
+
[0.6.0]: https://github.com/ffloyd/flows/compare/v0.5.1...v0.6.0
|
63
79
|
[0.5.1]: https://github.com/ffloyd/flows/compare/v0.5.0...v0.5.1
|
64
80
|
[0.5.0]: https://github.com/ffloyd/flows/compare/v0.4.0...v0.5.0
|
65
81
|
[0.4.0]: https://github.com/ffloyd/flows/compare/v0.3.0...v0.4.0
|
data/bin/errors
CHANGED
@@ -17,6 +17,7 @@ require_relative 'errors_cli/railway_error_demo'
|
|
17
17
|
require_relative 'errors_cli/result_error_demo'
|
18
18
|
require_relative 'errors_cli/scp_error_demo'
|
19
19
|
require_relative 'errors_cli/flow_error_demo'
|
20
|
+
require_relative 'errors_cli/interface_error_demo'
|
20
21
|
|
21
22
|
class ErrorsCLI
|
22
23
|
extend GLI::App
|
@@ -30,11 +31,11 @@ class ErrorsCLI
|
|
30
31
|
ctx.command name do |cmd|
|
31
32
|
cmd.action do |_, _, _|
|
32
33
|
puts title.green
|
33
|
-
puts(
|
34
|
+
puts("BEGIN#{'-' * (title.length - 5)}".color(:darkgray))
|
34
35
|
yield
|
35
36
|
rescue StandardError => err
|
36
37
|
puts err.message
|
37
|
-
puts(
|
38
|
+
puts("END#{'-' * (title.length - 3)}".color(:darkgray))
|
38
39
|
puts
|
39
40
|
end
|
40
41
|
end
|
@@ -125,6 +126,13 @@ class ErrorsCLI
|
|
125
126
|
FlowErrorDemo.invalid_node_route
|
126
127
|
end
|
127
128
|
end
|
129
|
+
|
130
|
+
desc 'Interface errors'
|
131
|
+
command :interface do |cmd|
|
132
|
+
make_cmd cmd, 'Missing Implementation', :missing_implementation do
|
133
|
+
InterfaceErrorDemo.missing_implementation
|
134
|
+
end
|
135
|
+
end
|
128
136
|
end
|
129
137
|
|
130
138
|
exit ErrorsCLI.run(ARGV)
|
data/flows.gemspec
CHANGED
@@ -21,6 +21,8 @@ Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength
|
|
21
21
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
22
|
spec.require_paths = ['lib']
|
23
23
|
|
24
|
+
spec.required_ruby_version = '>= 2.5'
|
25
|
+
|
24
26
|
# This library has no production dependencies.
|
25
27
|
# So, it will not block you from updating any dependencies in your project.
|
26
28
|
# So, don't add production dependencies.
|
data/lib/flows/contract.rb
CHANGED
@@ -394,9 +394,9 @@ module Flows
|
|
394
394
|
|
395
395
|
# :reek:UtilityFunction
|
396
396
|
def merge_nested_errors(description, nested_errors)
|
397
|
-
shifted = nested_errors.split("\n").map { |str|
|
397
|
+
shifted = nested_errors.split("\n").map { |str| " #{str}" }.join("\n")
|
398
398
|
|
399
|
-
description
|
399
|
+
"#{description}\n#{shifted}"
|
400
400
|
end
|
401
401
|
end
|
402
402
|
end
|
data/lib/flows/contract/error.rb
CHANGED
data/lib/flows/plugin.rb
CHANGED
@@ -136,6 +136,17 @@ module Flows
|
|
136
136
|
|
137
137
|
InitializerWrapper = Util::PrependToClass.make_module do
|
138
138
|
def initialize(*args, **kwargs, &block) # rubocop:disable Metrics/MethodLength
|
139
|
+
if @__dependencies_injected__
|
140
|
+
if kwargs.empty? # https://bugs.ruby-lang.org/issues/14415
|
141
|
+
super(*args, &block)
|
142
|
+
else
|
143
|
+
super(*args, **kwargs, &block)
|
144
|
+
end
|
145
|
+
|
146
|
+
return
|
147
|
+
end
|
148
|
+
@__dependencies_injected__ = true
|
149
|
+
|
139
150
|
klass = self.class
|
140
151
|
DependencyList.new(
|
141
152
|
klass: klass,
|
@@ -5,9 +5,7 @@ module Flows
|
|
5
5
|
#
|
6
6
|
# @api private
|
7
7
|
class DependencyList
|
8
|
-
attr_reader :definitions
|
9
|
-
attr_reader :provided_values
|
10
|
-
attr_reader :dependencies
|
8
|
+
attr_reader :definitions, :provided_values, :dependencies
|
11
9
|
|
12
10
|
def initialize(klass:, definitions:, provided_values:)
|
13
11
|
@klass = klass
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Flows
|
2
|
+
module Plugin
|
3
|
+
# Class extension to define Java/C#-like interfaces in Ruby.
|
4
|
+
#
|
5
|
+
# On target class initialization will check defined methods for existence.
|
6
|
+
#
|
7
|
+
# **Currently interface composition is not supported.** You cannot define
|
8
|
+
# 2 interface modules and include it into one class.
|
9
|
+
#
|
10
|
+
# @example Simple interface
|
11
|
+
# class MyAction
|
12
|
+
# extend Flows::Plugin::Interface
|
13
|
+
#
|
14
|
+
# defmethod :perform
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# class InvalidAction < MyAction; end
|
18
|
+
# InvalidAction.new
|
19
|
+
# # will raise an error
|
20
|
+
#
|
21
|
+
# class ValidAction < MyAction
|
22
|
+
# def perfrom
|
23
|
+
# puts 'Hello!'
|
24
|
+
# end
|
25
|
+
# end
|
26
|
+
# ValidAction.new.perform
|
27
|
+
# # => Hello!
|
28
|
+
#
|
29
|
+
# @example Interface as module
|
30
|
+
# module MyBehavior
|
31
|
+
# extend Flows::Plugin::Interface
|
32
|
+
#
|
33
|
+
# defmethod :my_method
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# class MyImplementation
|
37
|
+
# include MyBehaviour
|
38
|
+
#
|
39
|
+
# def my_method; end
|
40
|
+
# end
|
41
|
+
module Interface
|
42
|
+
# Base error class for interface errors.
|
43
|
+
class Error < ::Flows::Error; end
|
44
|
+
|
45
|
+
# Raised when you're missed some dependency.
|
46
|
+
class MissingMethodsError < Error
|
47
|
+
def initialize(klass, names)
|
48
|
+
@klass = klass
|
49
|
+
@names = names
|
50
|
+
end
|
51
|
+
|
52
|
+
def message
|
53
|
+
"Methods required by interface for #{@klass} are missing: #{@names.map(&:to_s).join(', ')}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
SingletonVarsSetup = Flows::Util::InheritableSingletonVars::DupStrategy.make_module(
|
58
|
+
'@interface_methods' => {}
|
59
|
+
)
|
60
|
+
|
61
|
+
include SingletonVarsSetup
|
62
|
+
|
63
|
+
InitializePatch = Flows::Util::PrependToClass.make_module do
|
64
|
+
def initialize(*)
|
65
|
+
klass = self.class
|
66
|
+
|
67
|
+
required_methods = klass.instance_variable_get(:@interface_methods).keys
|
68
|
+
missing_methods = required_methods - methods
|
69
|
+
|
70
|
+
raise MissingMethodsError.new(klass, missing_methods) if missing_methods.any?
|
71
|
+
|
72
|
+
super
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
include InitializePatch
|
77
|
+
|
78
|
+
def defmethod(method_name)
|
79
|
+
method_list = instance_variable_get(:@interface_methods)
|
80
|
+
method_list[method_name.to_sym] = { required_by: self }
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -39,7 +39,7 @@ module Flows
|
|
39
39
|
# Disables contract check and transformation for current class and children.
|
40
40
|
#
|
41
41
|
# @param enable [Boolean] if true - contracts are disabled
|
42
|
-
def skip_output_contract(enable
|
42
|
+
def skip_output_contract(enable: true)
|
43
43
|
@skip_output_contract_flag = enable
|
44
44
|
end
|
45
45
|
end
|
data/lib/flows/railway/step.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
module Flows
|
2
2
|
class Railway
|
3
|
-
|
4
|
-
Step = Struct.new(:name, :lambda, :next_step, keyword_init: true) do
|
5
|
-
NODE_PREPROCESSOR = ->(input, _, _) { [[], input.unwrap] }
|
3
|
+
NODE_PREPROCESSOR = ->(input, _, _) { [[], input.unwrap] }
|
6
4
|
|
7
|
-
|
8
|
-
|
5
|
+
NODE_POSTPROCESSOR = lambda do |output, context, meta|
|
6
|
+
context[:last_step] = meta[:name]
|
9
7
|
|
10
|
-
|
11
|
-
|
8
|
+
output
|
9
|
+
end
|
12
10
|
|
11
|
+
# @api private
|
12
|
+
Step = Struct.new(:name, :lambda, :next_step, keyword_init: true) do
|
13
13
|
def to_node(method_source)
|
14
14
|
Flows::Flow::Node.new(
|
15
15
|
body: lambda || method_source.method(name),
|
@@ -141,6 +141,46 @@ module Flows
|
|
141
141
|
# # steps implementations here
|
142
142
|
# end
|
143
143
|
#
|
144
|
+
# ## Simple injecting of nested pipelines
|
145
|
+
#
|
146
|
+
# If you provide some object which responds to `#call` instead of step name - this object will be used as a step body.
|
147
|
+
#
|
148
|
+
# class SubOperation < Flows::SharedContextPipeline
|
149
|
+
# step :hello
|
150
|
+
#
|
151
|
+
# def hello(**)
|
152
|
+
# ok(data: 'some data')
|
153
|
+
# end
|
154
|
+
# end
|
155
|
+
#
|
156
|
+
# class MainOperation < Flows::SharedContextPipeline
|
157
|
+
# step :init
|
158
|
+
# step SubOperation
|
159
|
+
#
|
160
|
+
# def init(**)
|
161
|
+
# ok(generated_by_init: true)
|
162
|
+
# end
|
163
|
+
# end
|
164
|
+
#
|
165
|
+
# MainOperation.call
|
166
|
+
# # => ok(generated_by_init: true, data: 'some data')
|
167
|
+
#
|
168
|
+
# You can use the same object multiple times in the same pipeline:
|
169
|
+
#
|
170
|
+
# step SubOperation
|
171
|
+
# step SubOperation
|
172
|
+
#
|
173
|
+
# If you need any input or output processing - refactor such step definition into normal step.
|
174
|
+
#
|
175
|
+
# This way has disadvantage: you cannot route to a such step because it has no explicit name.
|
176
|
+
# To handle this you can use alternative syntax:
|
177
|
+
#
|
178
|
+
# step :do_something, body: SubOperation
|
179
|
+
#
|
180
|
+
# Same features can be used with `mut_step`.
|
181
|
+
#
|
182
|
+
# This feature is primarily intended to simplify refactoring of big pipelines into smaller ones.
|
183
|
+
#
|
144
184
|
# ## Wrappers
|
145
185
|
#
|
146
186
|
# Sometimes you have to execute some steps inside SQL-transaction or something like this.
|
@@ -224,6 +264,9 @@ module Flows
|
|
224
264
|
#
|
225
265
|
# You may want to have some logic to execute before all steps, or after all, or before each, or after each.
|
226
266
|
# For example to inject generalized execution process logging.
|
267
|
+
#
|
268
|
+
# These callbacks are executed via `instance_exec` (in the context of instance).
|
269
|
+
#
|
227
270
|
# To achieve this you can use callbacks:
|
228
271
|
#
|
229
272
|
# class MySCP < Flows::SharedContextPipeline
|
@@ -277,10 +320,10 @@ module Flows
|
|
277
320
|
def call(**data) # rubocop:disable Metrics/MethodLength
|
278
321
|
klass = self.class
|
279
322
|
meta = {}
|
280
|
-
context = { data: data, meta: meta, class: klass }
|
323
|
+
context = { data: data, meta: meta, class: klass, instance: self }
|
281
324
|
|
282
325
|
klass.before_all_callbacks.each do |callback|
|
283
|
-
|
326
|
+
instance_exec(klass, data, meta, &callback)
|
284
327
|
end
|
285
328
|
|
286
329
|
flow_result = @__flow.call(nil, context: context)
|
@@ -292,7 +335,7 @@ module Flows
|
|
292
335
|
)
|
293
336
|
|
294
337
|
klass.after_all_callbacks.reduce(final_result) do |result, callback|
|
295
|
-
|
338
|
+
instance_exec(klass, result, data, meta, &callback)
|
296
339
|
end
|
297
340
|
end
|
298
341
|
end
|
@@ -12,10 +12,7 @@ module Flows
|
|
12
12
|
|
13
13
|
include SingletonVarsSetup
|
14
14
|
|
15
|
-
attr_reader :before_all_callbacks
|
16
|
-
attr_reader :after_all_callbacks
|
17
|
-
attr_reader :before_each_callbacks
|
18
|
-
attr_reader :after_each_callbacks
|
15
|
+
attr_reader :before_all_callbacks, :after_all_callbacks, :before_each_callbacks, :after_each_callbacks
|
19
16
|
|
20
17
|
def before_all(&callback)
|
21
18
|
before_all_callbacks << callback
|
@@ -16,15 +16,15 @@ module Flows
|
|
16
16
|
|
17
17
|
attr_reader :tracks
|
18
18
|
|
19
|
-
def step(name, router_def = DEFAULT_ROUTER_DEF,
|
19
|
+
def step(name, router_def = DEFAULT_ROUTER_DEF, body: nil)
|
20
20
|
tracks.add_step(
|
21
|
-
Step.new(name: name,
|
21
|
+
Step.new(name: name, body: body, router_def: router_def)
|
22
22
|
)
|
23
23
|
end
|
24
24
|
|
25
|
-
def mut_step(name, router_def = DEFAULT_ROUTER_DEF,
|
25
|
+
def mut_step(name, router_def = DEFAULT_ROUTER_DEF, body: nil)
|
26
26
|
tracks.add_step(
|
27
|
-
MutationStep.new(name: name,
|
27
|
+
MutationStep.new(name: name, body: body, router_def: router_def)
|
28
28
|
)
|
29
29
|
end
|
30
30
|
|
@@ -8,7 +8,7 @@ module Flows
|
|
8
8
|
class MutationStep < Step
|
9
9
|
NODE_PREPROCESSOR = lambda do |_input, context, node_meta|
|
10
10
|
context[:class].before_each_callbacks.each do |callback|
|
11
|
-
|
11
|
+
context[:instance].instance_exec(context[:class], node_meta[:name], context[:data], context[:meta], &callback)
|
12
12
|
end
|
13
13
|
|
14
14
|
[[context[:data]], EMPTY_HASH]
|
@@ -20,7 +20,8 @@ module Flows
|
|
20
20
|
else output ? EMPTY_OK : EMPTY_ERR
|
21
21
|
end.tap do |result|
|
22
22
|
context[:class].after_each_callbacks.each do |callback|
|
23
|
-
|
23
|
+
context[:instance]
|
24
|
+
.instance_exec(context[:class], node_meta[:name], result, context[:data], context[:meta], &callback)
|
24
25
|
end
|
25
26
|
end
|
26
27
|
end
|
@@ -3,12 +3,22 @@ module Flows
|
|
3
3
|
EMPTY_ARRAY = [].freeze
|
4
4
|
|
5
5
|
# @api private
|
6
|
-
Step = Struct.new(:name, :
|
6
|
+
Step = Struct.new(:name, :body, :router_def, :next_step, keyword_init: true) do
|
7
|
+
# :reek:ManualDispatch
|
8
|
+
def initialize(name:, body: nil, **rest)
|
9
|
+
if name.respond_to?(:call)
|
10
|
+
body = name
|
11
|
+
name = "#{body}+Step-Object-ID-#{object_id}"
|
12
|
+
end
|
13
|
+
|
14
|
+
super(name: name, body: body, **rest)
|
15
|
+
end
|
16
|
+
|
7
17
|
def to_node(pipeline_class)
|
8
18
|
klass = self.class
|
9
19
|
|
10
20
|
Flows::Flow::Node.new(
|
11
|
-
body:
|
21
|
+
body: body || pipeline_class.method(name),
|
12
22
|
router: router_def.to_router(next_step),
|
13
23
|
meta: { name: name },
|
14
24
|
preprocessor: klass::NODE_PREPROCESSOR,
|
@@ -21,7 +31,7 @@ module Flows
|
|
21
31
|
:NODE_PREPROCESSOR,
|
22
32
|
lambda do |_input, context, node_meta|
|
23
33
|
context[:class].before_each_callbacks.each do |callback|
|
24
|
-
|
34
|
+
context[:instance].instance_exec(context[:class], node_meta[:name], context[:data], context[:meta], &callback)
|
25
35
|
end
|
26
36
|
|
27
37
|
[EMPTY_ARRAY, context[:data]]
|
@@ -34,7 +44,8 @@ module Flows
|
|
34
44
|
context[:data].merge!(result.instance_variable_get(:@data))
|
35
45
|
|
36
46
|
context[:class].after_each_callbacks.each do |callback|
|
37
|
-
|
47
|
+
context[:instance]
|
48
|
+
.instance_exec(context[:class], node_meta[:name], result, context[:data], context[:meta], &callback)
|
38
49
|
end
|
39
50
|
|
40
51
|
result
|
@@ -24,14 +24,16 @@ module Flows
|
|
24
24
|
|
25
25
|
# @api private
|
26
26
|
module Migrator
|
27
|
-
|
28
|
-
|
29
|
-
|
27
|
+
# :reek:TooManyStatements is allowed here because it's impossible to split to smaller methods
|
28
|
+
def self.call(src_mod, dst_mod)
|
29
|
+
parent_var_list = src_mod.instance_variable_get(VAR_LIST_VAR_NAME)
|
30
|
+
child_var_list = dst_mod.instance_variable_get(VAR_LIST_VAR_NAME) || []
|
31
|
+
skip_list = parent_var_list & child_var_list
|
30
32
|
|
31
|
-
|
33
|
+
dst_mod.instance_variable_set(VAR_LIST_VAR_NAME, (child_var_list + parent_var_list).uniq)
|
32
34
|
|
33
|
-
parent_var_list.each do |name|
|
34
|
-
|
35
|
+
(parent_var_list - skip_list).each do |name|
|
36
|
+
dst_mod.instance_variable_set(name, src_mod.instance_variable_get(name).dup)
|
35
37
|
end
|
36
38
|
end
|
37
39
|
end
|
@@ -138,7 +138,8 @@ module Flows
|
|
138
138
|
# * you can include `Mod` into `Mod2`, then include `Mod2` into `Mod3` -
|
139
139
|
# desribed behavior works for include chain of any length.
|
140
140
|
#
|
141
|
-
#
|
141
|
+
# Each `include` generates a new prepend. Be careful about this when including
|
142
|
+
# generated module several times in the inheritance chain.
|
142
143
|
#
|
143
144
|
# @yield body for module which will be prepended
|
144
145
|
# @return [Module] module to be included or extended into your module
|
@@ -160,7 +161,8 @@ module Flows
|
|
160
161
|
mod.singleton_class.prepend(injector)
|
161
162
|
end
|
162
163
|
|
163
|
-
|
164
|
+
# :reek:TooManyStatements :reek:DuplicateMethodCall
|
165
|
+
def make_injector_mod(module_to_prepend) # rubocop:disable Metrics/MethodLength
|
164
166
|
Module.new.tap do |injector|
|
165
167
|
injector.define_method(:included) do |target_mod|
|
166
168
|
if target_mod.class == Class
|
@@ -171,6 +173,16 @@ module Flows
|
|
171
173
|
|
172
174
|
super(target_mod)
|
173
175
|
end
|
176
|
+
|
177
|
+
injector.define_method(:extended) do |target_mod|
|
178
|
+
if target_mod.class == Class
|
179
|
+
target_mod.prepend(module_to_prepend)
|
180
|
+
else # Module
|
181
|
+
target_mod.singleton_class.prepend injector
|
182
|
+
end
|
183
|
+
|
184
|
+
super(target_mod)
|
185
|
+
end
|
174
186
|
end
|
175
187
|
end
|
176
188
|
end
|
data/lib/flows/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flows
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Roman Kolesnev
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-09-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -387,6 +387,7 @@ files:
|
|
387
387
|
- ".reek.yml"
|
388
388
|
- ".rspec"
|
389
389
|
- ".rubocop.yml"
|
390
|
+
- ".rubocop_todo.yml"
|
390
391
|
- ".ruby-version"
|
391
392
|
- ".yardopts"
|
392
393
|
- CHANGELOG.md
|
@@ -434,6 +435,7 @@ files:
|
|
434
435
|
- bin/errors_cli/di_error_demo.rb
|
435
436
|
- bin/errors_cli/flow_error_demo.rb
|
436
437
|
- bin/errors_cli/flows_router_error_demo.rb
|
438
|
+
- bin/errors_cli/interface_error_demo.rb
|
437
439
|
- bin/errors_cli/oc_error_demo.rb
|
438
440
|
- bin/errors_cli/railway_error_demo.rb
|
439
441
|
- bin/errors_cli/result_error_demo.rb
|
@@ -473,6 +475,7 @@ files:
|
|
473
475
|
- lib/flows/plugin/dependency_injector/dependency_list.rb
|
474
476
|
- lib/flows/plugin/dependency_injector/errors.rb
|
475
477
|
- lib/flows/plugin/implicit_init.rb
|
478
|
+
- lib/flows/plugin/interface.rb
|
476
479
|
- lib/flows/plugin/output_contract.rb
|
477
480
|
- lib/flows/plugin/output_contract/dsl.rb
|
478
481
|
- lib/flows/plugin/output_contract/errors.rb
|
@@ -529,7 +532,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
529
532
|
requirements:
|
530
533
|
- - ">="
|
531
534
|
- !ruby/object:Gem::Version
|
532
|
-
version: '
|
535
|
+
version: '2.5'
|
533
536
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
534
537
|
requirements:
|
535
538
|
- - ">="
|