flows 0.2.0 → 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/.github/workflows/{build.yml → test.yml} +5 -10
- data/.gitignore +9 -1
- data/.mdlrc +1 -1
- data/.reek.yml +54 -0
- data/.rubocop.yml +26 -7
- data/.rubocop_todo.yml +27 -0
- data/.ruby-version +1 -1
- data/.yardopts +1 -0
- data/CHANGELOG.md +81 -0
- data/Gemfile +0 -6
- data/README.md +167 -363
- data/Rakefile +35 -1
- data/bin/.rubocop.yml +5 -0
- data/bin/all_the_errors +55 -0
- data/bin/benchmark +73 -105
- data/bin/benchmark_cli/compare.rb +118 -0
- data/bin/benchmark_cli/compare/a_plus_b.rb +22 -0
- data/bin/benchmark_cli/compare/base.rb +45 -0
- data/bin/benchmark_cli/compare/command.rb +47 -0
- data/bin/benchmark_cli/compare/ten_steps.rb +22 -0
- data/bin/benchmark_cli/examples.rb +23 -0
- data/bin/benchmark_cli/examples/.rubocop.yml +22 -0
- data/bin/benchmark_cli/examples/a_plus_b/dry_do.rb +23 -0
- data/bin/benchmark_cli/examples/a_plus_b/dry_transaction.rb +17 -0
- data/bin/benchmark_cli/examples/a_plus_b/flows_do.rb +22 -0
- data/bin/benchmark_cli/examples/a_plus_b/flows_railway.rb +13 -0
- data/bin/benchmark_cli/examples/a_plus_b/flows_scp.rb +13 -0
- data/bin/benchmark_cli/examples/a_plus_b/flows_scp_mut.rb +13 -0
- data/bin/benchmark_cli/examples/a_plus_b/flows_scp_oc.rb +21 -0
- data/bin/benchmark_cli/examples/a_plus_b/trailblazer.rb +15 -0
- data/bin/benchmark_cli/examples/ten_steps/dry_do.rb +70 -0
- data/bin/benchmark_cli/examples/ten_steps/dry_transaction.rb +64 -0
- data/bin/benchmark_cli/examples/ten_steps/flows_do.rb +69 -0
- data/bin/benchmark_cli/examples/ten_steps/flows_railway.rb +58 -0
- data/bin/benchmark_cli/examples/ten_steps/flows_scp.rb +58 -0
- data/bin/benchmark_cli/examples/ten_steps/flows_scp_mut.rb +58 -0
- data/bin/benchmark_cli/examples/ten_steps/flows_scp_oc.rb +66 -0
- data/bin/benchmark_cli/examples/ten_steps/trailblazer.rb +60 -0
- data/bin/benchmark_cli/helpers.rb +12 -0
- data/bin/benchmark_cli/ruby.rb +15 -0
- data/bin/benchmark_cli/ruby/command.rb +38 -0
- data/bin/benchmark_cli/ruby/method_exec.rb +71 -0
- data/bin/benchmark_cli/ruby/self_class.rb +69 -0
- data/bin/benchmark_cli/ruby/structs.rb +90 -0
- data/bin/console +1 -0
- data/bin/docserver +7 -0
- data/bin/errors +138 -0
- data/bin/errors_cli/contract_error_demo.rb +49 -0
- data/bin/errors_cli/di_error_demo.rb +38 -0
- data/bin/errors_cli/flow_error_demo.rb +22 -0
- data/bin/errors_cli/flows_router_error_demo.rb +15 -0
- data/bin/errors_cli/interface_error_demo.rb +17 -0
- data/bin/errors_cli/oc_error_demo.rb +40 -0
- data/bin/errors_cli/railway_error_demo.rb +10 -0
- data/bin/errors_cli/result_error_demo.rb +13 -0
- data/bin/errors_cli/scp_error_demo.rb +17 -0
- data/docs/README.md +3 -187
- data/docs/_sidebar.md +0 -24
- data/docs/index.html +1 -1
- data/flows.gemspec +27 -2
- data/forspell.dict +9 -0
- data/lefthook.yml +9 -0
- data/lib/flows.rb +11 -5
- data/lib/flows/contract.rb +402 -0
- data/lib/flows/contract/array.rb +55 -0
- data/lib/flows/contract/case_eq.rb +43 -0
- data/lib/flows/contract/compose.rb +77 -0
- data/lib/flows/contract/either.rb +53 -0
- data/lib/flows/contract/error.rb +24 -0
- data/lib/flows/contract/hash.rb +75 -0
- data/lib/flows/contract/hash_of.rb +70 -0
- data/lib/flows/contract/helpers.rb +22 -0
- data/lib/flows/contract/predicate.rb +34 -0
- data/lib/flows/contract/transformer.rb +50 -0
- data/lib/flows/contract/tuple.rb +70 -0
- data/lib/flows/flow.rb +96 -7
- data/lib/flows/flow/errors.rb +29 -0
- data/lib/flows/flow/node.rb +132 -0
- data/lib/flows/flow/router.rb +29 -0
- data/lib/flows/flow/router/custom.rb +59 -0
- data/lib/flows/flow/router/errors.rb +11 -0
- data/lib/flows/flow/router/simple.rb +25 -0
- data/lib/flows/plugin.rb +15 -0
- data/lib/flows/plugin/dependency_injector.rb +170 -0
- data/lib/flows/plugin/dependency_injector/dependency.rb +24 -0
- data/lib/flows/plugin/dependency_injector/dependency_definition.rb +16 -0
- data/lib/flows/plugin/dependency_injector/dependency_list.rb +55 -0
- data/lib/flows/plugin/dependency_injector/errors.rb +58 -0
- data/lib/flows/plugin/implicit_init.rb +45 -0
- data/lib/flows/plugin/interface.rb +84 -0
- data/lib/flows/plugin/output_contract.rb +85 -0
- data/lib/flows/plugin/output_contract/dsl.rb +48 -0
- data/lib/flows/plugin/output_contract/errors.rb +74 -0
- data/lib/flows/plugin/output_contract/wrapper.rb +55 -0
- data/lib/flows/plugin/profiler.rb +114 -0
- data/lib/flows/plugin/profiler/injector.rb +35 -0
- data/lib/flows/plugin/profiler/report.rb +48 -0
- data/lib/flows/plugin/profiler/report/events.rb +43 -0
- data/lib/flows/plugin/profiler/report/flat.rb +41 -0
- data/lib/flows/plugin/profiler/report/flat/method_report.rb +80 -0
- data/lib/flows/plugin/profiler/report/raw.rb +15 -0
- data/lib/flows/plugin/profiler/report/tree.rb +98 -0
- data/lib/flows/plugin/profiler/report/tree/calculated_node.rb +116 -0
- data/lib/flows/plugin/profiler/report/tree/node.rb +34 -0
- data/lib/flows/plugin/profiler/wrapper.rb +53 -0
- data/lib/flows/railway.rb +140 -34
- data/lib/flows/railway/dsl.rb +8 -18
- data/lib/flows/railway/errors.rb +8 -12
- data/lib/flows/railway/step.rb +24 -0
- data/lib/flows/railway/step_list.rb +38 -0
- data/lib/flows/result.rb +188 -2
- data/lib/flows/result/do.rb +158 -16
- data/lib/flows/result/err.rb +12 -6
- data/lib/flows/result/errors.rb +29 -17
- data/lib/flows/result/helpers.rb +25 -3
- data/lib/flows/result/ok.rb +12 -6
- data/lib/flows/shared_context_pipeline.rb +342 -0
- data/lib/flows/shared_context_pipeline/dsl.rb +12 -0
- data/lib/flows/shared_context_pipeline/dsl/callbacks.rb +35 -0
- data/lib/flows/shared_context_pipeline/dsl/tracks.rb +52 -0
- data/lib/flows/shared_context_pipeline/errors.rb +17 -0
- data/lib/flows/shared_context_pipeline/mutation_step.rb +30 -0
- data/lib/flows/shared_context_pipeline/router_definition.rb +21 -0
- data/lib/flows/shared_context_pipeline/step.rb +55 -0
- data/lib/flows/shared_context_pipeline/track.rb +54 -0
- data/lib/flows/shared_context_pipeline/track_list.rb +51 -0
- data/lib/flows/shared_context_pipeline/wrap.rb +73 -0
- data/lib/flows/util.rb +17 -0
- data/lib/flows/util/inheritable_singleton_vars.rb +86 -0
- data/lib/flows/util/inheritable_singleton_vars/dup_strategy.rb +100 -0
- data/lib/flows/util/inheritable_singleton_vars/isolation_strategy.rb +91 -0
- data/lib/flows/util/prepend_to_class.rb +191 -0
- data/lib/flows/version.rb +1 -1
- metadata +253 -38
- data/Gemfile.lock +0 -174
- data/bin/demo +0 -66
- data/bin/examples.rb +0 -195
- data/bin/profile_10steps +0 -106
- data/bin/ruby_benchmarks +0 -26
- data/docs/CNAME +0 -1
- data/docs/contributing/benchmarks_profiling.md +0 -3
- data/docs/contributing/local_development.md +0 -3
- data/docs/flow/direct_usage.md +0 -3
- data/docs/flow/general_idea.md +0 -3
- data/docs/operation/basic_usage.md +0 -1
- data/docs/operation/inject_steps.md +0 -3
- data/docs/operation/lambda_steps.md +0 -3
- data/docs/operation/result_shapes.md +0 -3
- data/docs/operation/routing_tracks.md +0 -3
- data/docs/operation/wrapping_steps.md +0 -3
- data/docs/overview/performance.md +0 -336
- data/docs/railway/basic_usage.md +0 -232
- data/docs/result_objects/basic_usage.md +0 -196
- data/docs/result_objects/do_notation.md +0 -139
- data/lib/flows/node.rb +0 -27
- data/lib/flows/operation.rb +0 -52
- data/lib/flows/operation/builder.rb +0 -130
- data/lib/flows/operation/builder/build_router.rb +0 -37
- data/lib/flows/operation/dsl.rb +0 -93
- data/lib/flows/operation/errors.rb +0 -75
- data/lib/flows/operation/executor.rb +0 -78
- data/lib/flows/railway/builder.rb +0 -68
- data/lib/flows/railway/executor.rb +0 -23
- data/lib/flows/result_router.rb +0 -14
- data/lib/flows/router.rb +0 -22
@@ -0,0 +1,100 @@
|
|
1
|
+
module Flows
|
2
|
+
module Util
|
3
|
+
module InheritableSingletonVars
|
4
|
+
# Strategy which uses `#dup` to copy variables to a child class.
|
5
|
+
#
|
6
|
+
# Can be applied several times to the same class.
|
7
|
+
#
|
8
|
+
# Can be applied in the middle of inheritance chain.
|
9
|
+
#
|
10
|
+
# When your value is a custom class you may need to adjust `#dup` behaviour.
|
11
|
+
# It can be done using `initialize_dup` method.
|
12
|
+
# Unfortunately it's not documented well in the standard library.
|
13
|
+
# So, [this will help you](https://blog.appsignal.com/2019/02/26/diving-into-dup-and-clone.html).
|
14
|
+
#
|
15
|
+
# @note If you change variables in a parent class after a child being defined
|
16
|
+
# it will have no effect on a child. Remember this when working in environments
|
17
|
+
# with tricky or experimental autoload mechanism.
|
18
|
+
#
|
19
|
+
# @see InheritableSingletonVars the parent module's documentation describes the problem this module solves.
|
20
|
+
#
|
21
|
+
# @since 0.4.0
|
22
|
+
module DupStrategy
|
23
|
+
VAR_LIST_VAR_NAME = :@inheritable_vars_with_dup
|
24
|
+
|
25
|
+
# @api private
|
26
|
+
module Migrator
|
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
|
32
|
+
|
33
|
+
dst_mod.instance_variable_set(VAR_LIST_VAR_NAME, (child_var_list + parent_var_list).uniq)
|
34
|
+
|
35
|
+
(parent_var_list - skip_list).each do |name|
|
36
|
+
dst_mod.instance_variable_set(name, src_mod.instance_variable_get(name).dup)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# @api private
|
42
|
+
module Injector
|
43
|
+
def included(mod)
|
44
|
+
Migrator.call(self, mod)
|
45
|
+
mod.singleton_class.prepend Injector
|
46
|
+
|
47
|
+
super
|
48
|
+
end
|
49
|
+
|
50
|
+
def extended(mod)
|
51
|
+
Migrator.call(self, mod)
|
52
|
+
mod.singleton_class.prepend Injector
|
53
|
+
|
54
|
+
super
|
55
|
+
end
|
56
|
+
|
57
|
+
def inherited(mod)
|
58
|
+
Migrator.call(self, mod)
|
59
|
+
mod.singleton_class.prepend Injector
|
60
|
+
|
61
|
+
super
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class << self
|
66
|
+
# Generates a module which applies behaviour and defaults for singleton variables.
|
67
|
+
#
|
68
|
+
# @example
|
69
|
+
# class MyClass
|
70
|
+
# SingletonVarsSetup = Flows::Util::InheritableSingletonVars::DupStrategy.make_module(
|
71
|
+
# :@my_list => []
|
72
|
+
# )
|
73
|
+
#
|
74
|
+
# include SingletonVarsSetup
|
75
|
+
# end
|
76
|
+
#
|
77
|
+
# @note Variable names should look like `:@var` or `'@var'`.
|
78
|
+
#
|
79
|
+
# @param vars_with_default [Hash<Symbol, String => Object>] keys are variable names,
|
80
|
+
# values are default values.
|
81
|
+
def make_module(vars_with_default = {})
|
82
|
+
Module.new.tap do |mod|
|
83
|
+
mod.instance_variable_set(VAR_LIST_VAR_NAME, vars_with_default.keys.map(&:to_sym))
|
84
|
+
init_vars(mod, vars_with_default)
|
85
|
+
mod.extend Injector
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def init_vars(mod, vars_with_default)
|
92
|
+
vars_with_default.each do |name, value|
|
93
|
+
mod.instance_variable_set(name, value)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module Flows
|
2
|
+
module Util
|
3
|
+
module InheritableSingletonVars
|
4
|
+
# Strategy which uses procs to generate initial values in target class and children.
|
5
|
+
#
|
6
|
+
# This strategy designed to make fully isolated singleton variables between classes.
|
7
|
+
#
|
8
|
+
# Can be applied several times to the same class.
|
9
|
+
#
|
10
|
+
# Can be applied in the middle of inheritance chain.
|
11
|
+
#
|
12
|
+
# @see InheritableSingletonVars the parent module's documentation describes the problem this module solves.
|
13
|
+
#
|
14
|
+
# @since 0.4.0
|
15
|
+
module IsolationStrategy
|
16
|
+
VAR_MAP_VAR_NAME = :@inheritable_vars_with_isolation
|
17
|
+
|
18
|
+
# @api private
|
19
|
+
module Migrator
|
20
|
+
def self.call(from, to)
|
21
|
+
parent_var_map = from.instance_variable_get(VAR_MAP_VAR_NAME)
|
22
|
+
child_var_map = to.instance_variable_get(VAR_MAP_VAR_NAME) || {}
|
23
|
+
|
24
|
+
to.instance_variable_set(VAR_MAP_VAR_NAME, child_var_map.merge(parent_var_map))
|
25
|
+
|
26
|
+
parent_var_map.each do |name, value_proc|
|
27
|
+
to.instance_variable_set(name, value_proc.call)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# @api private
|
33
|
+
module Injector
|
34
|
+
def included(mod)
|
35
|
+
Migrator.call(self, mod)
|
36
|
+
mod.singleton_class.prepend Injector
|
37
|
+
|
38
|
+
super
|
39
|
+
end
|
40
|
+
|
41
|
+
def extended(mod)
|
42
|
+
Migrator.call(self, mod)
|
43
|
+
mod.singleton_class.prepend Injector
|
44
|
+
|
45
|
+
super
|
46
|
+
end
|
47
|
+
|
48
|
+
def inherited(mod)
|
49
|
+
Migrator.call(self, mod)
|
50
|
+
mod.singleton_class.prepend Injector
|
51
|
+
|
52
|
+
super
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
class << self
|
57
|
+
# Applies behaviour and defaults for singleton variables.
|
58
|
+
#
|
59
|
+
# @example
|
60
|
+
# class MyClass
|
61
|
+
# SingletonVarsSetup = Flows::Util::InheritableSingletonVars::IsolationStrategy.make_module(
|
62
|
+
# :@my_list => -> { [] }
|
63
|
+
# )
|
64
|
+
#
|
65
|
+
# include SingletonVarsSetup
|
66
|
+
# end
|
67
|
+
#
|
68
|
+
# @note Variable names should look like `:@var` or `'@var'`.
|
69
|
+
#
|
70
|
+
# @param vars_with_default [Hash<Symbol, String => Proc>] keys are variable names,
|
71
|
+
# values are procs or lambdas which return default values.
|
72
|
+
def make_module(vars_with_default = {})
|
73
|
+
Module.new.tap do |mod|
|
74
|
+
mod.instance_variable_set(VAR_MAP_VAR_NAME, vars_with_default.dup)
|
75
|
+
init_vars(mod, vars_with_default)
|
76
|
+
mod.extend Injector
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def init_vars(mod, vars_with_default)
|
83
|
+
vars_with_default.each do |name, value_proc|
|
84
|
+
mod.instance_variable_set(name, value_proc.call)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,191 @@
|
|
1
|
+
module Flows
|
2
|
+
module Util
|
3
|
+
# In the situation when a module is included into another module and only afterwards included into class,
|
4
|
+
# allows to force particular module to be prepended to a class only.
|
5
|
+
#
|
6
|
+
# When you write some module to abstract out some behaviour you may
|
7
|
+
# need a way to expand initializer behaviour of a target class.
|
8
|
+
# You can prepend a module with an initializer wrapper inside `.included(mod)`
|
9
|
+
# or `.extended(mod)` callbacks. But it will not work if you include your module into module
|
10
|
+
# and only after to a class. It's one of the cases when `PrependToClass` can help you.
|
11
|
+
#
|
12
|
+
# Let's show it on example: we need a module which expands initializer to accept `:data`
|
13
|
+
# keyword argument and sets its value:
|
14
|
+
#
|
15
|
+
# class MyClass
|
16
|
+
# prepend HasData
|
17
|
+
#
|
18
|
+
# attr_reader :greeting
|
19
|
+
#
|
20
|
+
# def initialize
|
21
|
+
# @greeting = 'Hello'
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# module HasData
|
26
|
+
# attr_reader :data
|
27
|
+
#
|
28
|
+
# def initialize(*args, **kwargs, &block)
|
29
|
+
# @data = kwargs[:data]
|
30
|
+
#
|
31
|
+
# filtered_kwargs = kwargs.reject { |k, _| k == :data }
|
32
|
+
#
|
33
|
+
# if filtered_kwargs.empty? # https://bugs.ruby-lang.org/issues/14415
|
34
|
+
# super(*args, &block)
|
35
|
+
# else
|
36
|
+
# super(*args, **filtered_kwargs, &block)
|
37
|
+
# end
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# def big_data
|
41
|
+
# data.upcase
|
42
|
+
# end
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
# x = MyClass.new(data: 'aaa')
|
46
|
+
#
|
47
|
+
# x.greeting
|
48
|
+
# # => 'Hello'
|
49
|
+
#
|
50
|
+
# x.data
|
51
|
+
# # => 'aaa'
|
52
|
+
#
|
53
|
+
# x.big_data
|
54
|
+
# # => 'aaa'
|
55
|
+
#
|
56
|
+
# This implementation works, but has a problem:
|
57
|
+
#
|
58
|
+
# class AnotherClass
|
59
|
+
# include Stuff
|
60
|
+
#
|
61
|
+
# attr_reader :greeting
|
62
|
+
#
|
63
|
+
# def initialize
|
64
|
+
# @greeting = 'Hello'
|
65
|
+
# end
|
66
|
+
# end
|
67
|
+
#
|
68
|
+
# module Stuff
|
69
|
+
# prepend HasData
|
70
|
+
# end
|
71
|
+
#
|
72
|
+
# x = AnotherClass.new(data: 'aaa')
|
73
|
+
# # ArgumentError: wrong number of arguments (given 1, expected 0)
|
74
|
+
#
|
75
|
+
# This happens because `prepend` prepends our patch to `Stuff` module, not class.
|
76
|
+
# {PrependToClass} solves this problem:
|
77
|
+
#
|
78
|
+
# module HasData
|
79
|
+
# attr_reader :data
|
80
|
+
#
|
81
|
+
# InitializePatch = Flows::Util::PrependToClass.make_module do
|
82
|
+
# def initialize(*args, **kwargs, &block)
|
83
|
+
# @data = kwargs[:data]
|
84
|
+
#
|
85
|
+
# filtered_kwargs = kwargs.reject { |k, _| k == :data }
|
86
|
+
#
|
87
|
+
# if filtered_kwargs.empty? # https://bugs.ruby-lang.org/issues/14415
|
88
|
+
# super(*args, &block)
|
89
|
+
# else
|
90
|
+
# super(*args, **filtered_kwargs, &block)
|
91
|
+
# end
|
92
|
+
# end
|
93
|
+
# end
|
94
|
+
#
|
95
|
+
# include InitializePatch
|
96
|
+
# end
|
97
|
+
#
|
98
|
+
# module Stuff
|
99
|
+
# include HasData
|
100
|
+
# end
|
101
|
+
#
|
102
|
+
# class MyClass
|
103
|
+
# include Stuff
|
104
|
+
#
|
105
|
+
# attr_reader :greeting
|
106
|
+
#
|
107
|
+
# def initialize
|
108
|
+
# @greeting = 'Hello'
|
109
|
+
# end
|
110
|
+
# end
|
111
|
+
#
|
112
|
+
# x = MyClass.new(data: 'data')
|
113
|
+
#
|
114
|
+
# x.data
|
115
|
+
# # => 'data'
|
116
|
+
#
|
117
|
+
# x.greeting
|
118
|
+
# # => 'hello'
|
119
|
+
#
|
120
|
+
# @note this solution is designed to patch `include` behaviour and
|
121
|
+
# has no effect on `extend`.
|
122
|
+
module PrependToClass
|
123
|
+
class << self
|
124
|
+
# Allows to prepend some module to class when
|
125
|
+
# host module included into class.
|
126
|
+
#
|
127
|
+
# Under the hood two modules are created:
|
128
|
+
#
|
129
|
+
# * "to prepend" module made from provided block
|
130
|
+
# * "container" module which will be returned by this method
|
131
|
+
#
|
132
|
+
# When you include "container" module into your module `Mod`
|
133
|
+
# you're enabling the following behaviour:
|
134
|
+
#
|
135
|
+
# * when `Mod` included into class - "to prepend" module will be prepended to class
|
136
|
+
# * when `Mod` is included into some module `Mod2` - `Mod2` also will
|
137
|
+
# prepend "to prepend" module when included into class.
|
138
|
+
# * you can include `Mod` into `Mod2`, then include `Mod2` into `Mod3` -
|
139
|
+
# desribed behavior works for include chain of any length.
|
140
|
+
#
|
141
|
+
# Each `include` generates a new prepend. Be careful about this when including
|
142
|
+
# generated module several times in the inheritance chain.
|
143
|
+
#
|
144
|
+
# @yield body for module which will be prepended
|
145
|
+
# @return [Module] module to be included or extended into your module
|
146
|
+
def make_module(&module_body)
|
147
|
+
Module.new.tap do |mod|
|
148
|
+
to_prepend_mod = Module.new(&module_body)
|
149
|
+
mod.const_set(:ToPrepend, to_prepend_mod)
|
150
|
+
|
151
|
+
set_injector_mod(mod, to_prepend_mod)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
private
|
156
|
+
|
157
|
+
def set_injector_mod(mod, module_to_prepend)
|
158
|
+
injector = make_injector_mod(module_to_prepend)
|
159
|
+
|
160
|
+
mod.const_set(:Injector, injector)
|
161
|
+
mod.singleton_class.prepend(injector)
|
162
|
+
end
|
163
|
+
|
164
|
+
# :reek:TooManyStatements :reek:DuplicateMethodCall
|
165
|
+
def make_injector_mod(module_to_prepend) # rubocop:disable Metrics/MethodLength
|
166
|
+
Module.new.tap do |injector|
|
167
|
+
injector.define_method(:included) do |target_mod|
|
168
|
+
if target_mod.class == Class
|
169
|
+
target_mod.prepend(module_to_prepend)
|
170
|
+
else # Module
|
171
|
+
target_mod.singleton_class.prepend injector
|
172
|
+
end
|
173
|
+
|
174
|
+
super(target_mod)
|
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
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
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:
|
11
|
+
date: 2020-09-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '13.0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '13.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: yard
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: forspell
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,6 +80,48 @@ dependencies:
|
|
66
80
|
- - "~>"
|
67
81
|
- !ruby/object:Gem::Version
|
68
82
|
version: 0.0.8
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: inch
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: mdl
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: reek
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
69
125
|
- !ruby/object:Gem::Dependency
|
70
126
|
name: rubocop
|
71
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -122,6 +178,20 @@ dependencies:
|
|
122
178
|
- - ">="
|
123
179
|
- !ruby/object:Gem::Version
|
124
180
|
version: '0'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: awesome_print
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - ">="
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0'
|
188
|
+
type: :development
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - ">="
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
125
195
|
- !ruby/object:Gem::Dependency
|
126
196
|
name: pry
|
127
197
|
requirement: !ruby/object:Gem::Requirement
|
@@ -178,6 +248,20 @@ dependencies:
|
|
178
248
|
- - ">="
|
179
249
|
- !ruby/object:Gem::Version
|
180
250
|
version: '0'
|
251
|
+
- !ruby/object:Gem::Dependency
|
252
|
+
name: kalibera
|
253
|
+
requirement: !ruby/object:Gem::Requirement
|
254
|
+
requirements:
|
255
|
+
- - ">="
|
256
|
+
- !ruby/object:Gem::Version
|
257
|
+
version: '0'
|
258
|
+
type: :development
|
259
|
+
prerelease: false
|
260
|
+
version_requirements: !ruby/object:Gem::Requirement
|
261
|
+
requirements:
|
262
|
+
- - ">="
|
263
|
+
- !ruby/object:Gem::Version
|
264
|
+
version: '0'
|
181
265
|
- !ruby/object:Gem::Dependency
|
182
266
|
name: ruby-prof
|
183
267
|
requirement: !ruby/object:Gem::Requirement
|
@@ -206,6 +290,62 @@ dependencies:
|
|
206
290
|
- - ">="
|
207
291
|
- !ruby/object:Gem::Version
|
208
292
|
version: '0'
|
293
|
+
- !ruby/object:Gem::Dependency
|
294
|
+
name: gli
|
295
|
+
requirement: !ruby/object:Gem::Requirement
|
296
|
+
requirements:
|
297
|
+
- - ">="
|
298
|
+
- !ruby/object:Gem::Version
|
299
|
+
version: '0'
|
300
|
+
type: :development
|
301
|
+
prerelease: false
|
302
|
+
version_requirements: !ruby/object:Gem::Requirement
|
303
|
+
requirements:
|
304
|
+
- - ">="
|
305
|
+
- !ruby/object:Gem::Version
|
306
|
+
version: '0'
|
307
|
+
- !ruby/object:Gem::Dependency
|
308
|
+
name: rainbow
|
309
|
+
requirement: !ruby/object:Gem::Requirement
|
310
|
+
requirements:
|
311
|
+
- - ">="
|
312
|
+
- !ruby/object:Gem::Version
|
313
|
+
version: '0'
|
314
|
+
type: :development
|
315
|
+
prerelease: false
|
316
|
+
version_requirements: !ruby/object:Gem::Requirement
|
317
|
+
requirements:
|
318
|
+
- - ">="
|
319
|
+
- !ruby/object:Gem::Version
|
320
|
+
version: '0'
|
321
|
+
- !ruby/object:Gem::Dependency
|
322
|
+
name: warning
|
323
|
+
requirement: !ruby/object:Gem::Requirement
|
324
|
+
requirements:
|
325
|
+
- - ">="
|
326
|
+
- !ruby/object:Gem::Version
|
327
|
+
version: '0'
|
328
|
+
type: :development
|
329
|
+
prerelease: false
|
330
|
+
version_requirements: !ruby/object:Gem::Requirement
|
331
|
+
requirements:
|
332
|
+
- - ">="
|
333
|
+
- !ruby/object:Gem::Version
|
334
|
+
version: '0'
|
335
|
+
- !ruby/object:Gem::Dependency
|
336
|
+
name: dry-monads
|
337
|
+
requirement: !ruby/object:Gem::Requirement
|
338
|
+
requirements:
|
339
|
+
- - "~>"
|
340
|
+
- !ruby/object:Gem::Version
|
341
|
+
version: '1.3'
|
342
|
+
type: :development
|
343
|
+
prerelease: false
|
344
|
+
version_requirements: !ruby/object:Gem::Requirement
|
345
|
+
requirements:
|
346
|
+
- - "~>"
|
347
|
+
- !ruby/object:Gem::Version
|
348
|
+
version: '1.3'
|
209
349
|
- !ruby/object:Gem::Dependency
|
210
350
|
name: dry-transaction
|
211
351
|
requirement: !ruby/object:Gem::Requirement
|
@@ -241,69 +381,143 @@ executables: []
|
|
241
381
|
extensions: []
|
242
382
|
extra_rdoc_files: []
|
243
383
|
files:
|
244
|
-
- ".github/workflows/
|
384
|
+
- ".github/workflows/test.yml"
|
245
385
|
- ".gitignore"
|
246
386
|
- ".mdlrc"
|
387
|
+
- ".reek.yml"
|
247
388
|
- ".rspec"
|
248
389
|
- ".rubocop.yml"
|
390
|
+
- ".rubocop_todo.yml"
|
249
391
|
- ".ruby-version"
|
392
|
+
- ".yardopts"
|
393
|
+
- CHANGELOG.md
|
250
394
|
- CODE_OF_CONDUCT.md
|
251
395
|
- Gemfile
|
252
|
-
- Gemfile.lock
|
253
396
|
- LICENSE.txt
|
254
397
|
- README.md
|
255
398
|
- Rakefile
|
399
|
+
- bin/.rubocop.yml
|
400
|
+
- bin/all_the_errors
|
256
401
|
- bin/benchmark
|
402
|
+
- bin/benchmark_cli/compare.rb
|
403
|
+
- bin/benchmark_cli/compare/a_plus_b.rb
|
404
|
+
- bin/benchmark_cli/compare/base.rb
|
405
|
+
- bin/benchmark_cli/compare/command.rb
|
406
|
+
- bin/benchmark_cli/compare/ten_steps.rb
|
407
|
+
- bin/benchmark_cli/examples.rb
|
408
|
+
- bin/benchmark_cli/examples/.rubocop.yml
|
409
|
+
- bin/benchmark_cli/examples/a_plus_b/dry_do.rb
|
410
|
+
- bin/benchmark_cli/examples/a_plus_b/dry_transaction.rb
|
411
|
+
- bin/benchmark_cli/examples/a_plus_b/flows_do.rb
|
412
|
+
- bin/benchmark_cli/examples/a_plus_b/flows_railway.rb
|
413
|
+
- bin/benchmark_cli/examples/a_plus_b/flows_scp.rb
|
414
|
+
- bin/benchmark_cli/examples/a_plus_b/flows_scp_mut.rb
|
415
|
+
- bin/benchmark_cli/examples/a_plus_b/flows_scp_oc.rb
|
416
|
+
- bin/benchmark_cli/examples/a_plus_b/trailblazer.rb
|
417
|
+
- bin/benchmark_cli/examples/ten_steps/dry_do.rb
|
418
|
+
- bin/benchmark_cli/examples/ten_steps/dry_transaction.rb
|
419
|
+
- bin/benchmark_cli/examples/ten_steps/flows_do.rb
|
420
|
+
- bin/benchmark_cli/examples/ten_steps/flows_railway.rb
|
421
|
+
- bin/benchmark_cli/examples/ten_steps/flows_scp.rb
|
422
|
+
- bin/benchmark_cli/examples/ten_steps/flows_scp_mut.rb
|
423
|
+
- bin/benchmark_cli/examples/ten_steps/flows_scp_oc.rb
|
424
|
+
- bin/benchmark_cli/examples/ten_steps/trailblazer.rb
|
425
|
+
- bin/benchmark_cli/helpers.rb
|
426
|
+
- bin/benchmark_cli/ruby.rb
|
427
|
+
- bin/benchmark_cli/ruby/command.rb
|
428
|
+
- bin/benchmark_cli/ruby/method_exec.rb
|
429
|
+
- bin/benchmark_cli/ruby/self_class.rb
|
430
|
+
- bin/benchmark_cli/ruby/structs.rb
|
257
431
|
- bin/console
|
258
|
-
- bin/
|
259
|
-
- bin/
|
260
|
-
- bin/
|
261
|
-
- bin/
|
432
|
+
- bin/docserver
|
433
|
+
- bin/errors
|
434
|
+
- bin/errors_cli/contract_error_demo.rb
|
435
|
+
- bin/errors_cli/di_error_demo.rb
|
436
|
+
- bin/errors_cli/flow_error_demo.rb
|
437
|
+
- bin/errors_cli/flows_router_error_demo.rb
|
438
|
+
- bin/errors_cli/interface_error_demo.rb
|
439
|
+
- bin/errors_cli/oc_error_demo.rb
|
440
|
+
- bin/errors_cli/railway_error_demo.rb
|
441
|
+
- bin/errors_cli/result_error_demo.rb
|
442
|
+
- bin/errors_cli/scp_error_demo.rb
|
262
443
|
- bin/setup
|
263
444
|
- docs/.nojekyll
|
264
|
-
- docs/CNAME
|
265
445
|
- docs/README.md
|
266
446
|
- docs/_sidebar.md
|
267
|
-
- docs/contributing/benchmarks_profiling.md
|
268
|
-
- docs/contributing/local_development.md
|
269
|
-
- docs/flow/direct_usage.md
|
270
|
-
- docs/flow/general_idea.md
|
271
447
|
- docs/index.html
|
272
|
-
- docs/operation/basic_usage.md
|
273
|
-
- docs/operation/inject_steps.md
|
274
|
-
- docs/operation/lambda_steps.md
|
275
|
-
- docs/operation/result_shapes.md
|
276
|
-
- docs/operation/routing_tracks.md
|
277
|
-
- docs/operation/wrapping_steps.md
|
278
|
-
- docs/overview/performance.md
|
279
|
-
- docs/railway/basic_usage.md
|
280
|
-
- docs/result_objects/basic_usage.md
|
281
|
-
- docs/result_objects/do_notation.md
|
282
448
|
- flows.gemspec
|
283
449
|
- forspell.dict
|
284
450
|
- lefthook.yml
|
285
451
|
- lib/flows.rb
|
452
|
+
- lib/flows/contract.rb
|
453
|
+
- lib/flows/contract/array.rb
|
454
|
+
- lib/flows/contract/case_eq.rb
|
455
|
+
- lib/flows/contract/compose.rb
|
456
|
+
- lib/flows/contract/either.rb
|
457
|
+
- lib/flows/contract/error.rb
|
458
|
+
- lib/flows/contract/hash.rb
|
459
|
+
- lib/flows/contract/hash_of.rb
|
460
|
+
- lib/flows/contract/helpers.rb
|
461
|
+
- lib/flows/contract/predicate.rb
|
462
|
+
- lib/flows/contract/transformer.rb
|
463
|
+
- lib/flows/contract/tuple.rb
|
286
464
|
- lib/flows/flow.rb
|
287
|
-
- lib/flows/
|
288
|
-
- lib/flows/
|
289
|
-
- lib/flows/
|
290
|
-
- lib/flows/
|
291
|
-
- lib/flows/
|
292
|
-
- lib/flows/
|
293
|
-
- lib/flows/
|
465
|
+
- lib/flows/flow/errors.rb
|
466
|
+
- lib/flows/flow/node.rb
|
467
|
+
- lib/flows/flow/router.rb
|
468
|
+
- lib/flows/flow/router/custom.rb
|
469
|
+
- lib/flows/flow/router/errors.rb
|
470
|
+
- lib/flows/flow/router/simple.rb
|
471
|
+
- lib/flows/plugin.rb
|
472
|
+
- lib/flows/plugin/dependency_injector.rb
|
473
|
+
- lib/flows/plugin/dependency_injector/dependency.rb
|
474
|
+
- lib/flows/plugin/dependency_injector/dependency_definition.rb
|
475
|
+
- lib/flows/plugin/dependency_injector/dependency_list.rb
|
476
|
+
- lib/flows/plugin/dependency_injector/errors.rb
|
477
|
+
- lib/flows/plugin/implicit_init.rb
|
478
|
+
- lib/flows/plugin/interface.rb
|
479
|
+
- lib/flows/plugin/output_contract.rb
|
480
|
+
- lib/flows/plugin/output_contract/dsl.rb
|
481
|
+
- lib/flows/plugin/output_contract/errors.rb
|
482
|
+
- lib/flows/plugin/output_contract/wrapper.rb
|
483
|
+
- lib/flows/plugin/profiler.rb
|
484
|
+
- lib/flows/plugin/profiler/injector.rb
|
485
|
+
- lib/flows/plugin/profiler/report.rb
|
486
|
+
- lib/flows/plugin/profiler/report/events.rb
|
487
|
+
- lib/flows/plugin/profiler/report/flat.rb
|
488
|
+
- lib/flows/plugin/profiler/report/flat/method_report.rb
|
489
|
+
- lib/flows/plugin/profiler/report/raw.rb
|
490
|
+
- lib/flows/plugin/profiler/report/tree.rb
|
491
|
+
- lib/flows/plugin/profiler/report/tree/calculated_node.rb
|
492
|
+
- lib/flows/plugin/profiler/report/tree/node.rb
|
493
|
+
- lib/flows/plugin/profiler/wrapper.rb
|
294
494
|
- lib/flows/railway.rb
|
295
|
-
- lib/flows/railway/builder.rb
|
296
495
|
- lib/flows/railway/dsl.rb
|
297
496
|
- lib/flows/railway/errors.rb
|
298
|
-
- lib/flows/railway/
|
497
|
+
- lib/flows/railway/step.rb
|
498
|
+
- lib/flows/railway/step_list.rb
|
299
499
|
- lib/flows/result.rb
|
300
500
|
- lib/flows/result/do.rb
|
301
501
|
- lib/flows/result/err.rb
|
302
502
|
- lib/flows/result/errors.rb
|
303
503
|
- lib/flows/result/helpers.rb
|
304
504
|
- lib/flows/result/ok.rb
|
305
|
-
- lib/flows/
|
306
|
-
- lib/flows/
|
505
|
+
- lib/flows/shared_context_pipeline.rb
|
506
|
+
- lib/flows/shared_context_pipeline/dsl.rb
|
507
|
+
- lib/flows/shared_context_pipeline/dsl/callbacks.rb
|
508
|
+
- lib/flows/shared_context_pipeline/dsl/tracks.rb
|
509
|
+
- lib/flows/shared_context_pipeline/errors.rb
|
510
|
+
- lib/flows/shared_context_pipeline/mutation_step.rb
|
511
|
+
- lib/flows/shared_context_pipeline/router_definition.rb
|
512
|
+
- lib/flows/shared_context_pipeline/step.rb
|
513
|
+
- lib/flows/shared_context_pipeline/track.rb
|
514
|
+
- lib/flows/shared_context_pipeline/track_list.rb
|
515
|
+
- lib/flows/shared_context_pipeline/wrap.rb
|
516
|
+
- lib/flows/util.rb
|
517
|
+
- lib/flows/util/inheritable_singleton_vars.rb
|
518
|
+
- lib/flows/util/inheritable_singleton_vars/dup_strategy.rb
|
519
|
+
- lib/flows/util/inheritable_singleton_vars/isolation_strategy.rb
|
520
|
+
- lib/flows/util/prepend_to_class.rb
|
307
521
|
- lib/flows/version.rb
|
308
522
|
- profile/.keep
|
309
523
|
homepage: https://github.com/ffloyd/flows
|
@@ -318,7 +532,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
318
532
|
requirements:
|
319
533
|
- - ">="
|
320
534
|
- !ruby/object:Gem::Version
|
321
|
-
version: '
|
535
|
+
version: '2.5'
|
322
536
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
323
537
|
requirements:
|
324
538
|
- - ">="
|
@@ -328,5 +542,6 @@ requirements: []
|
|
328
542
|
rubygems_version: 3.0.3
|
329
543
|
signing_key:
|
330
544
|
specification_version: 4
|
331
|
-
summary: Ruby framework for building
|
545
|
+
summary: Ruby framework for building your Business Logic Layer inside Rails and other
|
546
|
+
frameworks.
|
332
547
|
test_files: []
|