flows 0.4.0 → 0.5.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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.mdlrc +1 -1
  3. data/.reek.yml +12 -0
  4. data/CHANGELOG.md +16 -0
  5. data/Gemfile.lock +1 -1
  6. data/README.md +12 -2
  7. data/Rakefile +1 -1
  8. data/bin/all_the_errors +8 -0
  9. data/bin/errors +12 -0
  10. data/bin/errors_cli/flow_error_demo.rb +22 -0
  11. data/docs/README.md +1 -1
  12. data/lib/flows/contract/case_eq.rb +3 -1
  13. data/lib/flows/flow/errors.rb +29 -0
  14. data/lib/flows/flow/node.rb +1 -0
  15. data/lib/flows/flow/router/custom.rb +5 -0
  16. data/lib/flows/flow/router/simple.rb +5 -0
  17. data/lib/flows/flow/router.rb +4 -0
  18. data/lib/flows/flow.rb +21 -0
  19. data/lib/flows/plugin/dependency_injector.rb +5 -5
  20. data/lib/flows/plugin/output_contract/dsl.rb +15 -3
  21. data/lib/flows/plugin/output_contract/wrapper.rb +14 -12
  22. data/lib/flows/plugin/output_contract.rb +1 -0
  23. data/lib/flows/plugin/profiler/injector.rb +35 -0
  24. data/lib/flows/plugin/profiler/report/events.rb +43 -0
  25. data/lib/flows/plugin/profiler/report/flat/method_report.rb +81 -0
  26. data/lib/flows/plugin/profiler/report/flat.rb +41 -0
  27. data/lib/flows/plugin/profiler/report/raw.rb +15 -0
  28. data/lib/flows/plugin/profiler/report/tree/calculated_node.rb +116 -0
  29. data/lib/flows/plugin/profiler/report/tree/node.rb +35 -0
  30. data/lib/flows/plugin/profiler/report/tree.rb +98 -0
  31. data/lib/flows/plugin/profiler/report.rb +48 -0
  32. data/lib/flows/plugin/profiler/wrapper.rb +53 -0
  33. data/lib/flows/plugin/profiler.rb +114 -0
  34. data/lib/flows/plugin.rb +1 -0
  35. data/lib/flows/railway/dsl.rb +3 -2
  36. data/lib/flows/result/do.rb +6 -8
  37. data/lib/flows/shared_context_pipeline/dsl/callbacks.rb +38 -0
  38. data/lib/flows/shared_context_pipeline/dsl/tracks.rb +52 -0
  39. data/lib/flows/shared_context_pipeline/dsl.rb +5 -56
  40. data/lib/flows/shared_context_pipeline/mutation_step.rb +6 -8
  41. data/lib/flows/shared_context_pipeline/step.rb +6 -8
  42. data/lib/flows/shared_context_pipeline/track.rb +2 -15
  43. data/lib/flows/shared_context_pipeline/track_list.rb +11 -6
  44. data/lib/flows/shared_context_pipeline/wrap.rb +64 -0
  45. data/lib/flows/shared_context_pipeline.rb +109 -26
  46. data/lib/flows/util/inheritable_singleton_vars/dup_strategy.rb +40 -51
  47. data/lib/flows/util/inheritable_singleton_vars/isolation_strategy.rb +39 -52
  48. data/lib/flows/util/inheritable_singleton_vars.rb +22 -15
  49. data/lib/flows/util/prepend_to_class.rb +43 -9
  50. data/lib/flows/version.rb +1 -1
  51. metadata +18 -2
@@ -16,25 +16,38 @@ module Flows
16
16
  VAR_MAP_VAR_NAME = :@inheritable_vars_with_isolation
17
17
 
18
18
  # @api private
19
- module InheritanceCallback
20
- def inherited(child_class)
21
- IsolationStrategy.migrate(self, child_class)
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) || {}
22
23
 
23
- super
24
- end
24
+ to.instance_variable_set(VAR_MAP_VAR_NAME, child_var_map.merge(parent_var_map))
25
25
 
26
- def included(child_mod)
27
- IsolationStrategy.migrate(self, child_mod)
26
+ parent_var_map.each do |name, value_proc|
27
+ to.instance_variable_set(name, value_proc.call)
28
+ end
29
+ end
30
+ end
28
31
 
29
- child_mod.singleton_class.prepend InheritanceCallback
32
+ # @api private
33
+ module Injector
34
+ def included(mod)
35
+ Migrator.call(self, mod)
36
+ mod.singleton_class.prepend Injector
30
37
 
31
38
  super
32
39
  end
33
40
 
34
- def extended(child_mod)
35
- IsolationStrategy.migrate(self, child_mod)
41
+ def extended(mod)
42
+ Migrator.call(self, mod)
43
+ mod.singleton_class.prepend Injector
44
+
45
+ super
46
+ end
36
47
 
37
- child_mod.singleton_class.prepend InheritanceCallback
48
+ def inherited(mod)
49
+ Migrator.call(self, mod)
50
+ mod.singleton_class.prepend Injector
38
51
 
39
52
  super
40
53
  end
@@ -43,60 +56,34 @@ module Flows
43
56
  class << self
44
57
  # Applies behaviour and defaults for singleton variables.
45
58
  #
46
- # @note Variable names should look like `:@var` or `'@var'`.
47
- #
48
- # @param klass [Class] target class.
49
- # @param attrs_with_default [Hash<Symbol, String => Proc>] keys are variable names,
50
- # values are procs or lambdas which return default values.
51
- #
52
59
  # @example
53
60
  # class MyClass
54
- # Flows::Util::InheritableSingletonVars::IsolationStrategy.call(
55
- # self,
61
+ # SingletonVarsSetup = Flows::Util::InheritableSingletonVars::IsolationStrategy.make_module(
56
62
  # :@my_list => -> { [] }
57
63
  # )
64
+ #
65
+ # include SingletonVarsSetup
58
66
  # end
59
- def call(klass, attrs_with_default = {})
60
- init_variables_with_default_values(klass, attrs_with_default)
61
-
62
- var_defaults = attrs_with_default
63
- add_variables_to_store(klass, var_defaults)
64
-
65
- inject_inheritance_hook(klass)
66
- end
67
-
68
- # Moves variables between modules
69
67
  #
70
- # @api private
71
- def migrate(from_mod, to_mod)
72
- new_var_map = from_mod.instance_variable_get(VAR_MAP_VAR_NAME).dup
73
-
74
- to_mod.instance_variable_set(VAR_MAP_VAR_NAME, new_var_map)
75
-
76
- new_var_map.each do |name, default_value_proc|
77
- to_mod.instance_variable_set(name, default_value_proc.call)
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
78
77
  end
79
78
  end
80
79
 
81
80
  private
82
81
 
83
- def init_variables_with_default_values(klass, attrs_with_default)
84
- attrs_with_default.each do |name, default_value_proc|
85
- klass.instance_variable_set(name, default_value_proc.call)
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)
86
85
  end
87
86
  end
88
-
89
- def add_variables_to_store(klass, var_defaults)
90
- store = klass.instance_variable_get(VAR_MAP_VAR_NAME) || {}
91
- next_store = store.merge(var_defaults)
92
-
93
- klass.instance_variable_set(VAR_MAP_VAR_NAME, next_store)
94
- end
95
-
96
- def inject_inheritance_hook(klass)
97
- singleton = klass.singleton_class
98
- singleton.prepend(InheritanceCallback) unless singleton.is_a?(InheritanceCallback)
99
- end
100
87
  end
101
88
  end
102
89
  end
@@ -41,30 +41,37 @@ module Flows
41
41
  # Each strategy here is using following way of injecting into yours abstract classes:
42
42
  #
43
43
  # class BaseSomething
44
- # Flows::Util::InheritableSingletonVars::SomeStrategy.call(
45
- # self,
46
- # **rest_of_the_options_here
44
+ # SingletonVarsSetup = Flows::Util::InheritableSingletonVars::SomeStrategy.make_module(
45
+ # **options_here
47
46
  # )
47
+ #
48
+ # include SingeltonVarsSetup # extend also will work
48
49
  # end
49
50
  #
50
51
  # In case of extensions and mixins:
51
52
  #
52
53
  # module MyExtension
53
- # def self.extended(mod)
54
- # Flows::Util::InheritableSingletonVars::SomeStrategy.call(
55
- # mod,
56
- # **rest_of_the_options_here
57
- # )
58
- # end
54
+ # SingletonVarsSetup = Flows::Util::InheritableSingletonVars::SomeStrategy.make_module(
55
+ # **options_here
56
+ # )
57
+ #
58
+ # include SingeltonVarsSetup # extend also will work
59
+ # end
60
+ #
61
+ # class SomethingA
62
+ # extend MyExtension
59
63
  # end
60
64
  #
61
65
  # module MyMixin
62
- # def self.included(mod)
63
- # Flows::Util::InheritableSingletonVars::SomeStrategy.call(
64
- # mod,
65
- # **rest_of_the_options_here
66
- # )
67
- # end
66
+ # SingletonVarsSetup = Flows::Util::InheritableSingletonVars::SomeStrategy.make_module(
67
+ # **options_here
68
+ # )
69
+ #
70
+ # include SingeltonVarsSetup # extend also will work
71
+ # end
72
+ #
73
+ # class SomethingB
74
+ # include MyMixin
68
75
  # end
69
76
  #
70
77
  # Moreover, you can use multiple strategies in the same class.
@@ -78,7 +78,7 @@ module Flows
78
78
  # module HasData
79
79
  # attr_reader :data
80
80
  #
81
- # module InitializePatch
81
+ # InitializePatch = Flows::Util::PrependToClass.make_module do
82
82
  # def initialize(*args, **kwargs, &block)
83
83
  # @data = kwargs[:data]
84
84
  #
@@ -92,7 +92,7 @@ module Flows
92
92
  # end
93
93
  # end
94
94
  #
95
- # Flows::Util::PrependToClass.call(self, InitializePatch)
95
+ # include InitializePatch
96
96
  # end
97
97
  #
98
98
  # module Stuff
@@ -113,20 +113,54 @@ module Flows
113
113
  #
114
114
  # x.data
115
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`.
116
122
  module PrependToClass
117
123
  class << self
118
- # When `mod` is included into class in any way `module_to_prepend`
119
- # will be prepended to the class.
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.
120
140
  #
121
- # @param mod [Module] host module
122
- # @param module_to_prepend [Module] module to be prepended to a class
123
- def call(mod, module_to_prepend)
124
- mod.singleton_class.prepend injector(module_to_prepend)
141
+ # Moreover, this behaviour also works with `extend`, not only `include`.
142
+ #
143
+ # @yield body for module which will be prepended
144
+ # @return [Module] module to be included or extended into your module
145
+ def make_module(&module_body)
146
+ Module.new.tap do |mod|
147
+ to_prepend_mod = Module.new(&module_body)
148
+ mod.const_set(:ToPrepend, to_prepend_mod)
149
+
150
+ set_injector_mod(mod, to_prepend_mod)
151
+ end
125
152
  end
126
153
 
127
154
  private
128
155
 
129
- def injector(module_to_prepend)
156
+ def set_injector_mod(mod, module_to_prepend)
157
+ injector = make_injector_mod(module_to_prepend)
158
+
159
+ mod.const_set(:Injector, injector)
160
+ mod.singleton_class.prepend(injector)
161
+ end
162
+
163
+ def make_injector_mod(module_to_prepend)
130
164
  Module.new.tap do |injector|
131
165
  injector.define_method(:included) do |target_mod|
132
166
  if target_mod.class == Class
data/lib/flows/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Flows
2
- VERSION = '0.4.0'.freeze
2
+ VERSION = '0.5.0'.freeze
3
3
  end
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.0
4
+ version: 0.5.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-04-21 00:00:00.000000000 Z
11
+ date: 2020-05-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -433,6 +433,7 @@ files:
433
433
  - bin/errors
434
434
  - bin/errors_cli/contract_error_demo.rb
435
435
  - bin/errors_cli/di_error_demo.rb
436
+ - bin/errors_cli/flow_error_demo.rb
436
437
  - bin/errors_cli/flows_router_error_demo.rb
437
438
  - bin/errors_cli/oc_error_demo.rb
438
439
  - bin/errors_cli/railway_error_demo.rb
@@ -460,6 +461,7 @@ files:
460
461
  - lib/flows/contract/transformer.rb
461
462
  - lib/flows/contract/tuple.rb
462
463
  - lib/flows/flow.rb
464
+ - lib/flows/flow/errors.rb
463
465
  - lib/flows/flow/node.rb
464
466
  - lib/flows/flow/router.rb
465
467
  - lib/flows/flow/router/custom.rb
@@ -476,6 +478,17 @@ files:
476
478
  - lib/flows/plugin/output_contract/dsl.rb
477
479
  - lib/flows/plugin/output_contract/errors.rb
478
480
  - lib/flows/plugin/output_contract/wrapper.rb
481
+ - lib/flows/plugin/profiler.rb
482
+ - lib/flows/plugin/profiler/injector.rb
483
+ - lib/flows/plugin/profiler/report.rb
484
+ - lib/flows/plugin/profiler/report/events.rb
485
+ - lib/flows/plugin/profiler/report/flat.rb
486
+ - lib/flows/plugin/profiler/report/flat/method_report.rb
487
+ - lib/flows/plugin/profiler/report/raw.rb
488
+ - lib/flows/plugin/profiler/report/tree.rb
489
+ - lib/flows/plugin/profiler/report/tree/calculated_node.rb
490
+ - lib/flows/plugin/profiler/report/tree/node.rb
491
+ - lib/flows/plugin/profiler/wrapper.rb
479
492
  - lib/flows/railway.rb
480
493
  - lib/flows/railway/dsl.rb
481
494
  - lib/flows/railway/errors.rb
@@ -489,12 +502,15 @@ files:
489
502
  - lib/flows/result/ok.rb
490
503
  - lib/flows/shared_context_pipeline.rb
491
504
  - lib/flows/shared_context_pipeline/dsl.rb
505
+ - lib/flows/shared_context_pipeline/dsl/callbacks.rb
506
+ - lib/flows/shared_context_pipeline/dsl/tracks.rb
492
507
  - lib/flows/shared_context_pipeline/errors.rb
493
508
  - lib/flows/shared_context_pipeline/mutation_step.rb
494
509
  - lib/flows/shared_context_pipeline/router_definition.rb
495
510
  - lib/flows/shared_context_pipeline/step.rb
496
511
  - lib/flows/shared_context_pipeline/track.rb
497
512
  - lib/flows/shared_context_pipeline/track_list.rb
513
+ - lib/flows/shared_context_pipeline/wrap.rb
498
514
  - lib/flows/util.rb
499
515
  - lib/flows/util/inheritable_singleton_vars.rb
500
516
  - lib/flows/util/inheritable_singleton_vars/dup_strategy.rb