ni 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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