ni 0.1.0 → 0.1.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 265a1f7cc75012e97066f5653b33bc25b77e7abc0d60fa4b626e295b81654048
4
- data.tar.gz: 26c58567835dcefddbb834ba7269203af72e19125dcf9df2b4d2bcf47b7a4dfc
3
+ metadata.gz: 2722909d396c8ab5b69d6eaeff89bd86e2f9348ed9cb0ce13c2e13b08cb12156
4
+ data.tar.gz: ab92b5e571b2863ffeff1e184157c1b51f29798daec0b41b8aff6bb83d99c619
5
5
  SHA512:
6
- metadata.gz: 14d145ecad87c1260831277f089a9c1fb2c9a92876e332e3a8cd88e217d11ea2b758e6df9f186b110d4efb93d3233ad58aa70082b1750e485db060e7f6a524c8
7
- data.tar.gz: 1e57c0a420648e1be62661d7be739fc448d9f8b02cff146438defdd8de1d0e36a5c9da56f9fa1acccac7df84c86667405dbfe32fac299d6aa69b05d55ea5b450
6
+ metadata.gz: e9983ebf7e41b12bb13ed3eb5b1572f8f4252c2f5b9cc36841fce42d8211eae378575830cc6af37c500581cb026adfd2af6627bcddd2b6096c3f0536a988dfde
7
+ data.tar.gz: 604430e4558babccf76befc9d164724ddac2901e65cf5c091b378f5a22940a51d2f4cae68dedc79f3c9fd18448bdd78868c4991592d7c50e5b1feff60c61eacc
@@ -0,0 +1,189 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ ni (0.1.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ actioncable (6.0.0)
10
+ actionpack (= 6.0.0)
11
+ nio4r (~> 2.0)
12
+ websocket-driver (>= 0.6.1)
13
+ actionmailbox (6.0.0)
14
+ actionpack (= 6.0.0)
15
+ activejob (= 6.0.0)
16
+ activerecord (= 6.0.0)
17
+ activestorage (= 6.0.0)
18
+ activesupport (= 6.0.0)
19
+ mail (>= 2.7.1)
20
+ actionmailer (6.0.0)
21
+ actionpack (= 6.0.0)
22
+ actionview (= 6.0.0)
23
+ activejob (= 6.0.0)
24
+ mail (~> 2.5, >= 2.5.4)
25
+ rails-dom-testing (~> 2.0)
26
+ actionpack (6.0.0)
27
+ actionview (= 6.0.0)
28
+ activesupport (= 6.0.0)
29
+ rack (~> 2.0)
30
+ rack-test (>= 0.6.3)
31
+ rails-dom-testing (~> 2.0)
32
+ rails-html-sanitizer (~> 1.0, >= 1.2.0)
33
+ actiontext (6.0.0)
34
+ actionpack (= 6.0.0)
35
+ activerecord (= 6.0.0)
36
+ activestorage (= 6.0.0)
37
+ activesupport (= 6.0.0)
38
+ nokogiri (>= 1.8.5)
39
+ actionview (6.0.0)
40
+ activesupport (= 6.0.0)
41
+ builder (~> 3.1)
42
+ erubi (~> 1.4)
43
+ rails-dom-testing (~> 2.0)
44
+ rails-html-sanitizer (~> 1.1, >= 1.2.0)
45
+ activejob (6.0.0)
46
+ activesupport (= 6.0.0)
47
+ globalid (>= 0.3.6)
48
+ activemodel (6.0.0)
49
+ activesupport (= 6.0.0)
50
+ activerecord (6.0.0)
51
+ activemodel (= 6.0.0)
52
+ activesupport (= 6.0.0)
53
+ activestorage (6.0.0)
54
+ actionpack (= 6.0.0)
55
+ activejob (= 6.0.0)
56
+ activerecord (= 6.0.0)
57
+ marcel (~> 0.3.1)
58
+ activesupport (6.0.0)
59
+ concurrent-ruby (~> 1.0, >= 1.0.2)
60
+ i18n (>= 0.7, < 2)
61
+ minitest (~> 5.1)
62
+ tzinfo (~> 1.1)
63
+ zeitwerk (~> 2.1, >= 2.1.8)
64
+ builder (3.2.3)
65
+ byebug (11.0.1)
66
+ coderay (1.1.2)
67
+ concurrent-ruby (1.1.5)
68
+ crass (1.0.4)
69
+ database_cleaner (1.7.0)
70
+ diff-lcs (1.3)
71
+ docile (1.3.2)
72
+ erubi (1.8.0)
73
+ globalid (0.4.2)
74
+ activesupport (>= 4.2.0)
75
+ i18n (1.6.0)
76
+ concurrent-ruby (~> 1.0)
77
+ json (2.2.0)
78
+ loofah (2.2.3)
79
+ crass (~> 1.0.2)
80
+ nokogiri (>= 1.5.9)
81
+ mail (2.7.1)
82
+ mini_mime (>= 0.1.1)
83
+ marcel (0.3.3)
84
+ mimemagic (~> 0.3.2)
85
+ method_source (0.9.2)
86
+ mimemagic (0.3.3)
87
+ mini_mime (1.0.2)
88
+ mini_portile2 (2.4.0)
89
+ minitest (5.11.3)
90
+ nio4r (2.5.1)
91
+ nokogiri (1.10.4)
92
+ mini_portile2 (~> 2.4.0)
93
+ pg (1.1.4)
94
+ pry (0.12.2)
95
+ coderay (~> 1.1.0)
96
+ method_source (~> 0.9.0)
97
+ rack (2.0.7)
98
+ rack-test (1.1.0)
99
+ rack (>= 1.0, < 3)
100
+ rails (6.0.0)
101
+ actioncable (= 6.0.0)
102
+ actionmailbox (= 6.0.0)
103
+ actionmailer (= 6.0.0)
104
+ actionpack (= 6.0.0)
105
+ actiontext (= 6.0.0)
106
+ actionview (= 6.0.0)
107
+ activejob (= 6.0.0)
108
+ activemodel (= 6.0.0)
109
+ activerecord (= 6.0.0)
110
+ activestorage (= 6.0.0)
111
+ activesupport (= 6.0.0)
112
+ bundler (>= 1.3.0)
113
+ railties (= 6.0.0)
114
+ sprockets-rails (>= 2.0.0)
115
+ rails-dom-testing (2.0.3)
116
+ activesupport (>= 4.2.0)
117
+ nokogiri (>= 1.6)
118
+ rails-dummy (0.1.0)
119
+ railties
120
+ rails-html-sanitizer (1.2.0)
121
+ loofah (~> 2.2, >= 2.2.2)
122
+ railties (6.0.0)
123
+ actionpack (= 6.0.0)
124
+ activesupport (= 6.0.0)
125
+ method_source
126
+ rake (>= 0.8.7)
127
+ thor (>= 0.20.3, < 2.0)
128
+ rake (10.5.0)
129
+ rspec (3.8.0)
130
+ rspec-core (~> 3.8.0)
131
+ rspec-expectations (~> 3.8.0)
132
+ rspec-mocks (~> 3.8.0)
133
+ rspec-core (3.8.2)
134
+ rspec-support (~> 3.8.0)
135
+ rspec-expectations (3.8.4)
136
+ diff-lcs (>= 1.2.0, < 2.0)
137
+ rspec-support (~> 3.8.0)
138
+ rspec-mocks (3.8.1)
139
+ diff-lcs (>= 1.2.0, < 2.0)
140
+ rspec-support (~> 3.8.0)
141
+ rspec-rails (3.8.2)
142
+ actionpack (>= 3.0)
143
+ activesupport (>= 3.0)
144
+ railties (>= 3.0)
145
+ rspec-core (~> 3.8.0)
146
+ rspec-expectations (~> 3.8.0)
147
+ rspec-mocks (~> 3.8.0)
148
+ rspec-support (~> 3.8.0)
149
+ rspec-support (3.8.2)
150
+ simplecov (0.17.1)
151
+ docile (~> 1.1)
152
+ json (>= 1.8, < 3)
153
+ simplecov-html (~> 0.10.0)
154
+ simplecov-html (0.10.2)
155
+ sprockets (3.7.2)
156
+ concurrent-ruby (~> 1.0)
157
+ rack (> 1, < 3)
158
+ sprockets-rails (3.2.1)
159
+ actionpack (>= 4.0)
160
+ activesupport (>= 4.0)
161
+ sprockets (>= 3.0.0)
162
+ thor (0.20.3)
163
+ thread_safe (0.3.6)
164
+ tzinfo (1.2.5)
165
+ thread_safe (~> 0.1)
166
+ websocket-driver (0.7.1)
167
+ websocket-extensions (>= 0.1.0)
168
+ websocket-extensions (0.1.4)
169
+ zeitwerk (2.1.10)
170
+
171
+ PLATFORMS
172
+ ruby
173
+
174
+ DEPENDENCIES
175
+ bundler (~> 1.17)
176
+ byebug
177
+ database_cleaner
178
+ ni!
179
+ pg
180
+ pry
181
+ rails
182
+ rails-dummy
183
+ rake (~> 10.0)
184
+ rspec (~> 3.0)
185
+ rspec-rails
186
+ simplecov
187
+
188
+ BUNDLED WITH
189
+ 1.17.3
@@ -0,0 +1,140 @@
1
+ module Ni
2
+ class ActionChain
3
+ attr_accessor :name, :description, :received_values, :returned_values, :units, :failure_callback, :rescues
4
+
5
+ def initialize(klass, name, description, &block)
6
+ @interactor_klass = klass
7
+ @name = name, @description = description
8
+ @units = block_given? ? [block.to_proc] : []
9
+ @failure_callback = nil
10
+ @rescues = []
11
+ @returned_values = []
12
+
13
+ self
14
+ ensure
15
+ update_chain
16
+ end
17
+
18
+ # Params methods
19
+
20
+ def receive(*args)
21
+ @received_values = args
22
+
23
+ self
24
+ ensure
25
+ update_chain
26
+ end
27
+
28
+ def provide(*args)
29
+ @returned_values = args
30
+
31
+ self
32
+ ensure
33
+ update_chain
34
+ end
35
+
36
+ # Flow methods
37
+
38
+ def then(*args, **options, &block)
39
+ if block_given?
40
+ @units << block.to_proc
41
+ else
42
+ @units << chain_builder(args, options)
43
+ end
44
+
45
+ self
46
+ ensure
47
+ update_chain
48
+ end
49
+
50
+ def isolate(*args, **options, &block)
51
+ if block_given?
52
+ raise 'Not Implemented yet'
53
+ else
54
+ first, last = args
55
+ @units << Ni::Flows::IsolatedInlineInteractor.new(first, (last || :perform), options)
56
+ end
57
+
58
+ self
59
+ ensure
60
+ update_chain
61
+ end
62
+
63
+ def failure(&block)
64
+ @failure_callback = block.to_proc
65
+
66
+ self
67
+ ensure
68
+ update_chain
69
+ end
70
+
71
+ def rescue_from(*args, &block)
72
+ args = [Exception] if args.empty?
73
+
74
+ @rescues << [args, block.to_proc]
75
+
76
+ self
77
+ ensure
78
+ update_chain
79
+ end
80
+
81
+ def wait_for(condition, options={})
82
+ @units << Ni::Flows::WaitForCondition.new(condition, @interactor_klass, options)
83
+
84
+ self
85
+ ensure
86
+ update_chain
87
+ end
88
+
89
+ def branch(*args, **options, &block)
90
+ @units << Ni::Flows::BranchInteractor.new(@interactor_klass, args, options, &block)
91
+
92
+ self
93
+ ensure
94
+ update_chain
95
+ end
96
+
97
+ def terminate!
98
+ @units << "context.terminate!"
99
+ ensure
100
+ update_chain
101
+ end
102
+
103
+ def cancel!
104
+ @units << "context.cancel!"
105
+ ensure
106
+ update_chain
107
+ end
108
+
109
+ def failure!
110
+ @units << "context.failure!"
111
+ ensure
112
+ update_chain
113
+ end
114
+
115
+ def success!
116
+ @units << "context.success!"
117
+ ensure
118
+ update_chain
119
+ end
120
+
121
+ private
122
+
123
+ def chain_builder(args, options)
124
+ first, last = args
125
+
126
+ case first
127
+ when Symbol, String
128
+ first
129
+ when Class
130
+ Ni::Flows::InlineInteractor.new(first, (last || :perform), options)
131
+ else
132
+ raise 'Invalid chain options'
133
+ end
134
+ end
135
+
136
+ def update_chain
137
+ @interactor_klass.defined_actions[name] = self
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,217 @@
1
+ module Ni
2
+ class Context
3
+ class Errors
4
+ include Enumerable
5
+
6
+ delegate :each, :empty?, :present?, :blank?, to: '@errors'
7
+
8
+ def initialize
9
+ @errors = {}
10
+ end
11
+
12
+ def add(key, message)
13
+ @errors[key] ||= []
14
+ @errors[key] << message
15
+ end
16
+
17
+ def []=(key, message)
18
+ @errors[key] ||= []
19
+ @errors[key] << message
20
+ end
21
+
22
+ def full_messages
23
+ @errors.values.flatten
24
+ end
25
+
26
+ def to_h
27
+ @errors
28
+ end
29
+
30
+ def to_json
31
+ to_h.to_json
32
+ end
33
+ end
34
+
35
+ attr_accessor :current_interactor, :current_action, :errors
36
+ attr_accessor :as_result, :system_uid, :continue_from, :external_system_uid
37
+ attr_accessor :halt_execution, :skip_the_rest_chain
38
+
39
+ delegate :each, :slice, to: '@data'
40
+
41
+ def initialize(interactor, action, system_uid = nil)
42
+ self.external_system_uid = system_uid
43
+ self.system_uid = system_uid || SecureRandom.hex(15)
44
+ self.current_interactor = interactor
45
+ self.current_action = action
46
+ self.errors = Errors.new
47
+ self.as_result = false
48
+ @data = {}
49
+ @success = true
50
+ @terminated = false
51
+ end
52
+
53
+ def success?
54
+ @success && valid?
55
+ end
56
+
57
+ def failed?
58
+ !@success || !valid?
59
+ end
60
+
61
+ def canceled?
62
+ !@success && valid?
63
+ end
64
+
65
+ def terminated?
66
+ @terminated
67
+ end
68
+
69
+ def failure!
70
+ @success = false
71
+ end
72
+
73
+ def cancel!
74
+ @success = false
75
+ end
76
+
77
+ def can_perform_next_step?
78
+ success? && !terminated?
79
+ end
80
+
81
+ def success!
82
+ @terminated = true
83
+ end
84
+
85
+ def terminate!
86
+ @success = false
87
+ @terminated = true
88
+ end
89
+
90
+ def assign_data!(params)
91
+ @data.merge!(params)
92
+ end
93
+
94
+ def assign_current_interactor!(interactor)
95
+ self.current_interactor = interactor
96
+ end
97
+
98
+ def continue_from!(name_or_interactor)
99
+ name = name_or_interactor.is_a?(Class) ? name_or_interactor.interactor_id! : name_or_interactor
100
+ self.continue_from = name
101
+ end
102
+
103
+ def halt_execution!
104
+ self.halt_execution = true
105
+ end
106
+
107
+ def execution_halted?
108
+ halt_execution.present?
109
+ end
110
+
111
+ def skip_the_rest_chain!
112
+ self.skip_the_rest_chain = true
113
+ end
114
+
115
+ def chain_skipped?
116
+ skip_the_rest_chain.present?
117
+ ensure
118
+ # I now it's a bad Idea to mutate state in predicates but this operation should be atomic
119
+ self.skip_the_rest_chain = false
120
+ end
121
+
122
+ def wait_completed!
123
+ self.continue_from = nil
124
+ end
125
+
126
+ def wait_for_execution?
127
+ continue_from.present?
128
+ end
129
+
130
+ def should_be_restored?
131
+ wait_for_execution? || self.external_system_uid.present?
132
+ end
133
+
134
+ def resultify!
135
+ self.as_result = true
136
+
137
+ self
138
+ end
139
+
140
+ def within_interactor(interactor, action)
141
+ stored_interactor = self.current_interactor
142
+ stored_action = self.current_action
143
+
144
+ self.current_interactor = interactor
145
+ self.current_action = action
146
+
147
+ result = yield
148
+
149
+ self.current_interactor = stored_interactor
150
+ self.current_action = stored_action
151
+
152
+ result
153
+ end
154
+
155
+ def [](name)
156
+ unless allow_to_read?(name)
157
+ raise "The `#{name}` is not allowed to read"
158
+ end
159
+
160
+ raw_get(name)
161
+ end
162
+
163
+ def []=(name, value)
164
+ unless allow_to_write?(name)
165
+ raise "The `#{name}` is not allowed to write"
166
+ end
167
+
168
+ raw_set(name, value)
169
+ end
170
+
171
+ # raw_get was defined only for internal purposes only. Please do not use it in your code
172
+ def raw_get(name)
173
+ @data[name.to_sym]
174
+ end
175
+
176
+ # raw_set was defined only for internal purposes only. Please do not use it in your code
177
+ def raw_set(name, value)
178
+ @data[name.to_sym] = value
179
+ end
180
+
181
+ def respond_to?(name, include_private=false)
182
+ super || has_key?(name)
183
+ end
184
+
185
+ def has_key?(name)
186
+ @data.has_key?(name.to_sym)
187
+ end
188
+
189
+ def valid?
190
+ errors.empty?
191
+ end
192
+
193
+ def invalid?
194
+ !valid?
195
+ end
196
+
197
+ def fetch(*args)
198
+ args.map { |name| self[name] }
199
+ end
200
+
201
+ def allow_to_read?(name)
202
+ as_result || self.current_interactor.allow_to_read?(self.current_action, name)
203
+ end
204
+
205
+ def allow_to_write?(name)
206
+ as_result || self.current_interactor.allow_to_write?(self.current_action, name)
207
+ end
208
+
209
+ def method_missing(name, *args, &block)
210
+ if name.to_s.ends_with?('=')
211
+ self[name[0..-2].to_sym] = args.first
212
+ else
213
+ self[name]
214
+ end
215
+ end
216
+ end
217
+ end