strongmind-platform-sdk 3.15.0 → 3.19.9
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 +1 -1
- data/Gemfile +10 -3
- data/Gemfile.lock +235 -52
- data/README.md +124 -4
- data/lib/platform_sdk/active_record/data_pipelineable.rb +74 -0
- data/lib/platform_sdk/data_pipeline/data_pipeline_client.rb +1 -0
- data/lib/platform_sdk/identity/clients.rb +16 -15
- data/lib/platform_sdk/identity.rb +1 -0
- data/lib/platform_sdk/spec_support/shared_examples/data_pipelineable_examples.rb +90 -0
- data/lib/platform_sdk/spec_support/shared_examples/one_roster_data_pipelineable_examples.rb +110 -0
- data/lib/platform_sdk/spec_support.rb +10 -0
- data/lib/platform_sdk/version.rb +1 -1
- data/lib/platform_sdk.rb +2 -0
- metadata +34 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3b4e9c7bfc3e7b93b4aabdfa138eaaa574725e36d087df67e15e239a4de595f4
|
4
|
+
data.tar.gz: 30acfbe7eb2487768dabe23ff6920b3b95f600e52039cde1f6ab5587cbdccc4e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7539aa22ff674560101e36c8b668bd43a9d601ddec913865595cd9a8e81d19703b1482b2afd73dd1e44b25183ef1c80fd39701416e8460fd605817fc3676bb36
|
7
|
+
data.tar.gz: 1ca026d1104f79143f564c60c9b81473e2794b8501cb161e9df85c17e762ce8c5d5d339757deaecff9e4df623b3e228e2635da9f62779cbb27b7997c10487f0f
|
data/.rubocop.yml
CHANGED
data/Gemfile
CHANGED
@@ -8,16 +8,23 @@ gem "strongmind-oneroster-client", "~> 2.0.3"
|
|
8
8
|
# Specify your gem's dependencies in platform_sdk-ruby-sdk.gemspec
|
9
9
|
gemspec
|
10
10
|
|
11
|
-
gem "factory_bot"
|
12
|
-
gem "faker"
|
13
11
|
gem "faraday"
|
14
12
|
gem "faraday-retry"
|
15
13
|
gem "jwt", "~> 1.5", ">= 1.5.4"
|
16
14
|
gem "learnosity-sdk", "~> 0.2.2"
|
17
15
|
gem "multi_json"
|
18
16
|
gem "rake", "~> 13.0"
|
19
|
-
gem "rspec"
|
17
|
+
gem "rspec"
|
20
18
|
gem "rubocop"
|
21
19
|
gem "sentry-ruby"
|
22
20
|
gem "webmock"
|
21
|
+
gem 'activesupport', '~> 7.1', '>= 7.1.3.2'
|
22
|
+
|
23
|
+
group :development, :test do
|
24
|
+
gem "sqlite3", "~> 1.4"
|
25
|
+
gem 'rspec-rails', '~> 6.1.0'
|
26
|
+
gem 'faker'
|
27
|
+
gem "factory_bot"
|
28
|
+
gem 'timecop'
|
29
|
+
end
|
23
30
|
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
strongmind-platform-sdk (3.
|
4
|
+
strongmind-platform-sdk (3.19.9)
|
5
|
+
activesupport (~> 7.1)
|
5
6
|
aws-sdk-secretsmanager (~> 1.66)
|
6
7
|
faraday (~> 2.5, >= 2.5.2)
|
7
8
|
faraday-retry
|
@@ -16,124 +17,301 @@ PATH
|
|
16
17
|
GEM
|
17
18
|
remote: https://rubygems.org/
|
18
19
|
specs:
|
19
|
-
|
20
|
+
actioncable (7.1.3.2)
|
21
|
+
actionpack (= 7.1.3.2)
|
22
|
+
activesupport (= 7.1.3.2)
|
23
|
+
nio4r (~> 2.0)
|
24
|
+
websocket-driver (>= 0.6.1)
|
25
|
+
zeitwerk (~> 2.6)
|
26
|
+
actionmailbox (7.1.3.2)
|
27
|
+
actionpack (= 7.1.3.2)
|
28
|
+
activejob (= 7.1.3.2)
|
29
|
+
activerecord (= 7.1.3.2)
|
30
|
+
activestorage (= 7.1.3.2)
|
31
|
+
activesupport (= 7.1.3.2)
|
32
|
+
mail (>= 2.7.1)
|
33
|
+
net-imap
|
34
|
+
net-pop
|
35
|
+
net-smtp
|
36
|
+
actionmailer (7.1.3.2)
|
37
|
+
actionpack (= 7.1.3.2)
|
38
|
+
actionview (= 7.1.3.2)
|
39
|
+
activejob (= 7.1.3.2)
|
40
|
+
activesupport (= 7.1.3.2)
|
41
|
+
mail (~> 2.5, >= 2.5.4)
|
42
|
+
net-imap
|
43
|
+
net-pop
|
44
|
+
net-smtp
|
45
|
+
rails-dom-testing (~> 2.2)
|
46
|
+
actionpack (7.1.3.2)
|
47
|
+
actionview (= 7.1.3.2)
|
48
|
+
activesupport (= 7.1.3.2)
|
49
|
+
nokogiri (>= 1.8.5)
|
50
|
+
racc
|
51
|
+
rack (>= 2.2.4)
|
52
|
+
rack-session (>= 1.0.1)
|
53
|
+
rack-test (>= 0.6.3)
|
54
|
+
rails-dom-testing (~> 2.2)
|
55
|
+
rails-html-sanitizer (~> 1.6)
|
56
|
+
actiontext (7.1.3.2)
|
57
|
+
actionpack (= 7.1.3.2)
|
58
|
+
activerecord (= 7.1.3.2)
|
59
|
+
activestorage (= 7.1.3.2)
|
60
|
+
activesupport (= 7.1.3.2)
|
61
|
+
globalid (>= 0.6.0)
|
62
|
+
nokogiri (>= 1.8.5)
|
63
|
+
actionview (7.1.3.2)
|
64
|
+
activesupport (= 7.1.3.2)
|
65
|
+
builder (~> 3.1)
|
66
|
+
erubi (~> 1.11)
|
67
|
+
rails-dom-testing (~> 2.2)
|
68
|
+
rails-html-sanitizer (~> 1.6)
|
69
|
+
activejob (7.1.3.2)
|
70
|
+
activesupport (= 7.1.3.2)
|
71
|
+
globalid (>= 0.3.6)
|
72
|
+
activemodel (7.1.3.2)
|
73
|
+
activesupport (= 7.1.3.2)
|
74
|
+
activerecord (7.1.3.2)
|
75
|
+
activemodel (= 7.1.3.2)
|
76
|
+
activesupport (= 7.1.3.2)
|
77
|
+
timeout (>= 0.4.0)
|
78
|
+
activestorage (7.1.3.2)
|
79
|
+
actionpack (= 7.1.3.2)
|
80
|
+
activejob (= 7.1.3.2)
|
81
|
+
activerecord (= 7.1.3.2)
|
82
|
+
activesupport (= 7.1.3.2)
|
83
|
+
marcel (~> 1.0)
|
84
|
+
activesupport (7.1.3.2)
|
85
|
+
base64
|
86
|
+
bigdecimal
|
20
87
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
88
|
+
connection_pool (>= 2.2.5)
|
89
|
+
drb
|
21
90
|
i18n (>= 1.6, < 2)
|
22
91
|
minitest (>= 5.1)
|
92
|
+
mutex_m
|
23
93
|
tzinfo (~> 2.0)
|
24
|
-
zeitwerk (~> 2.3)
|
25
94
|
addressable (2.8.6)
|
26
95
|
public_suffix (>= 2.0.2, < 6.0)
|
27
96
|
ast (2.4.2)
|
28
97
|
aws-eventstream (1.3.0)
|
29
|
-
aws-partitions (1.
|
30
|
-
aws-sdk-cloudwatch (1.
|
98
|
+
aws-partitions (1.934.0)
|
99
|
+
aws-sdk-cloudwatch (1.91.0)
|
31
100
|
aws-sdk-core (~> 3, >= 3.193.0)
|
32
101
|
aws-sigv4 (~> 1.1)
|
33
|
-
aws-sdk-core (3.
|
102
|
+
aws-sdk-core (3.196.1)
|
34
103
|
aws-eventstream (~> 1, >= 1.3.0)
|
35
104
|
aws-partitions (~> 1, >= 1.651.0)
|
36
105
|
aws-sigv4 (~> 1.8)
|
37
106
|
jmespath (~> 1, >= 1.6.1)
|
38
|
-
aws-sdk-secretsmanager (1.
|
107
|
+
aws-sdk-secretsmanager (1.95.0)
|
39
108
|
aws-sdk-core (~> 3, >= 3.193.0)
|
40
109
|
aws-sigv4 (~> 1.1)
|
41
110
|
aws-sigv4 (1.8.0)
|
42
111
|
aws-eventstream (~> 1, >= 1.0.2)
|
43
|
-
|
112
|
+
base64 (0.2.0)
|
113
|
+
bigdecimal (3.1.8)
|
114
|
+
builder (3.2.4)
|
44
115
|
concurrent-ruby (1.2.3)
|
45
116
|
connection_pool (2.4.1)
|
46
117
|
crack (1.0.0)
|
47
118
|
bigdecimal
|
48
119
|
rexml
|
49
|
-
|
120
|
+
crass (1.0.6)
|
121
|
+
date (3.3.4)
|
122
|
+
diff-lcs (1.5.1)
|
123
|
+
drb (2.2.1)
|
124
|
+
erubi (1.12.0)
|
50
125
|
ethon (0.16.0)
|
51
126
|
ffi (>= 1.15.0)
|
52
|
-
factory_bot (6.4.
|
127
|
+
factory_bot (6.4.6)
|
53
128
|
activesupport (>= 5.0.0)
|
54
|
-
faker (
|
129
|
+
faker (3.3.1)
|
55
130
|
i18n (>= 1.8.11, < 2)
|
56
|
-
faraday (2.
|
57
|
-
faraday-net_http (>= 2.0, < 3.
|
58
|
-
|
59
|
-
|
60
|
-
faraday-retry (2.1
|
131
|
+
faraday (2.9.0)
|
132
|
+
faraday-net_http (>= 2.0, < 3.2)
|
133
|
+
faraday-net_http (3.1.0)
|
134
|
+
net-http
|
135
|
+
faraday-retry (2.2.1)
|
61
136
|
faraday (~> 2.0)
|
62
|
-
ffi (1.
|
137
|
+
ffi (1.16.3)
|
138
|
+
globalid (1.2.1)
|
139
|
+
activesupport (>= 6.1)
|
63
140
|
hashdiff (1.1.0)
|
64
|
-
i18n (1.14.
|
141
|
+
i18n (1.14.5)
|
65
142
|
concurrent-ruby (~> 1.0)
|
143
|
+
io-console (0.7.2)
|
144
|
+
irb (1.13.1)
|
145
|
+
rdoc (>= 4.0.0)
|
146
|
+
reline (>= 0.4.2)
|
66
147
|
jmespath (1.6.2)
|
67
|
-
json (2.
|
148
|
+
json (2.7.2)
|
68
149
|
jwt (1.5.6)
|
150
|
+
language_server-protocol (3.17.0.3)
|
69
151
|
learnosity-sdk (0.2.2)
|
70
152
|
sys-uname (>= 1.0)
|
71
|
-
|
153
|
+
loofah (2.22.0)
|
154
|
+
crass (~> 1.0.2)
|
155
|
+
nokogiri (>= 1.12.0)
|
156
|
+
mail (2.8.1)
|
157
|
+
mini_mime (>= 0.1.1)
|
158
|
+
net-imap
|
159
|
+
net-pop
|
160
|
+
net-smtp
|
161
|
+
marcel (1.0.4)
|
162
|
+
mini_mime (1.1.5)
|
163
|
+
mini_portile2 (2.8.6)
|
164
|
+
minitest (5.22.3)
|
72
165
|
multi_json (1.15.0)
|
73
|
-
|
74
|
-
|
166
|
+
mutex_m (0.2.0)
|
167
|
+
net-http (0.4.1)
|
168
|
+
uri
|
169
|
+
net-imap (0.4.11)
|
170
|
+
date
|
171
|
+
net-protocol
|
172
|
+
net-pop (0.1.2)
|
173
|
+
net-protocol
|
174
|
+
net-protocol (0.2.2)
|
175
|
+
timeout
|
176
|
+
net-smtp (0.5.0)
|
177
|
+
net-protocol
|
178
|
+
nio4r (2.7.3)
|
179
|
+
nokogiri (1.16.5)
|
180
|
+
mini_portile2 (~> 2.8.2)
|
181
|
+
racc (~> 1.4)
|
182
|
+
nokogiri (1.16.5-x86_64-darwin)
|
183
|
+
racc (~> 1.4)
|
184
|
+
nokogiri (1.16.5-x86_64-linux)
|
185
|
+
racc (~> 1.4)
|
186
|
+
parallel (1.24.0)
|
187
|
+
parser (3.3.1.0)
|
75
188
|
ast (~> 2.4.1)
|
76
|
-
|
77
|
-
|
189
|
+
racc
|
190
|
+
psych (5.1.2)
|
191
|
+
stringio
|
192
|
+
public_suffix (5.0.5)
|
193
|
+
racc (1.7.3)
|
194
|
+
rack (3.0.11)
|
195
|
+
rack-session (2.0.0)
|
196
|
+
rack (>= 3.0.0)
|
197
|
+
rack-test (2.1.0)
|
198
|
+
rack (>= 1.3)
|
199
|
+
rackup (2.1.0)
|
200
|
+
rack (>= 3)
|
201
|
+
webrick (~> 1.8)
|
202
|
+
rails (7.1.3.2)
|
203
|
+
actioncable (= 7.1.3.2)
|
204
|
+
actionmailbox (= 7.1.3.2)
|
205
|
+
actionmailer (= 7.1.3.2)
|
206
|
+
actionpack (= 7.1.3.2)
|
207
|
+
actiontext (= 7.1.3.2)
|
208
|
+
actionview (= 7.1.3.2)
|
209
|
+
activejob (= 7.1.3.2)
|
210
|
+
activemodel (= 7.1.3.2)
|
211
|
+
activerecord (= 7.1.3.2)
|
212
|
+
activestorage (= 7.1.3.2)
|
213
|
+
activesupport (= 7.1.3.2)
|
214
|
+
bundler (>= 1.15.0)
|
215
|
+
railties (= 7.1.3.2)
|
216
|
+
rails-dom-testing (2.2.0)
|
217
|
+
activesupport (>= 5.0.0)
|
218
|
+
minitest
|
219
|
+
nokogiri (>= 1.6)
|
220
|
+
rails-html-sanitizer (1.6.0)
|
221
|
+
loofah (~> 2.21)
|
222
|
+
nokogiri (~> 1.14)
|
223
|
+
railties (7.1.3.2)
|
224
|
+
actionpack (= 7.1.3.2)
|
225
|
+
activesupport (= 7.1.3.2)
|
226
|
+
irb
|
227
|
+
rackup (>= 1.0.0)
|
228
|
+
rake (>= 12.2)
|
229
|
+
thor (~> 1.0, >= 1.2.2)
|
230
|
+
zeitwerk (~> 2.6)
|
78
231
|
rainbow (3.1.1)
|
79
|
-
rake (13.
|
80
|
-
|
232
|
+
rake (13.2.1)
|
233
|
+
rdoc (6.6.3.1)
|
234
|
+
psych (>= 4.0.0)
|
235
|
+
redis-client (0.22.2)
|
81
236
|
connection_pool
|
82
|
-
regexp_parser (2.
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
rspec-
|
88
|
-
|
89
|
-
rspec-
|
90
|
-
rspec-
|
237
|
+
regexp_parser (2.9.1)
|
238
|
+
reline (0.5.7)
|
239
|
+
io-console (~> 0.5)
|
240
|
+
rexml (3.2.6)
|
241
|
+
rspec (3.13.0)
|
242
|
+
rspec-core (~> 3.13.0)
|
243
|
+
rspec-expectations (~> 3.13.0)
|
244
|
+
rspec-mocks (~> 3.13.0)
|
245
|
+
rspec-core (3.13.0)
|
246
|
+
rspec-support (~> 3.13.0)
|
247
|
+
rspec-expectations (3.13.0)
|
91
248
|
diff-lcs (>= 1.2.0, < 2.0)
|
92
|
-
rspec-support (~> 3.
|
93
|
-
rspec-mocks (3.
|
249
|
+
rspec-support (~> 3.13.0)
|
250
|
+
rspec-mocks (3.13.1)
|
94
251
|
diff-lcs (>= 1.2.0, < 2.0)
|
95
|
-
rspec-support (~> 3.
|
96
|
-
rspec-
|
97
|
-
|
252
|
+
rspec-support (~> 3.13.0)
|
253
|
+
rspec-rails (6.1.2)
|
254
|
+
actionpack (>= 6.1)
|
255
|
+
activesupport (>= 6.1)
|
256
|
+
railties (>= 6.1)
|
257
|
+
rspec-core (~> 3.13)
|
258
|
+
rspec-expectations (~> 3.13)
|
259
|
+
rspec-mocks (~> 3.13)
|
260
|
+
rspec-support (~> 3.13)
|
261
|
+
rspec-support (3.13.1)
|
262
|
+
rubocop (1.63.5)
|
98
263
|
json (~> 2.3)
|
264
|
+
language_server-protocol (>= 3.17.0)
|
99
265
|
parallel (~> 1.10)
|
100
|
-
parser (>= 3.
|
266
|
+
parser (>= 3.3.0.2)
|
101
267
|
rainbow (>= 2.2.2, < 4.0)
|
102
268
|
regexp_parser (>= 1.8, < 3.0)
|
103
269
|
rexml (>= 3.2.5, < 4.0)
|
104
|
-
rubocop-ast (>= 1.
|
270
|
+
rubocop-ast (>= 1.31.1, < 2.0)
|
105
271
|
ruby-progressbar (~> 1.7)
|
106
272
|
unicode-display_width (>= 2.4.0, < 3.0)
|
107
|
-
rubocop-ast (1.
|
108
|
-
parser (>= 3.
|
273
|
+
rubocop-ast (1.31.3)
|
274
|
+
parser (>= 3.3.1.0)
|
109
275
|
ruby-progressbar (1.13.0)
|
110
|
-
|
111
|
-
|
276
|
+
sentry-ruby (5.17.3)
|
277
|
+
bigdecimal
|
112
278
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
113
279
|
sidekiq (7.2.4)
|
114
280
|
concurrent-ruby (< 2)
|
115
281
|
connection_pool (>= 2.3.0)
|
116
282
|
rack (>= 2.2.4)
|
117
283
|
redis-client (>= 0.19.0)
|
284
|
+
sqlite3 (1.7.3)
|
285
|
+
mini_portile2 (~> 2.8.0)
|
286
|
+
sqlite3 (1.7.3-x86_64-darwin)
|
287
|
+
sqlite3 (1.7.3-x86_64-linux)
|
288
|
+
stringio (3.1.0)
|
118
289
|
strongmind-oneroster-client (2.0.3)
|
119
290
|
json (~> 2.1, >= 2.1.0)
|
120
291
|
typhoeus (~> 1.0, >= 1.0.1)
|
121
|
-
strongmind-sidekiq-cloudwatchmetrics (2.6.
|
292
|
+
strongmind-sidekiq-cloudwatchmetrics (2.6.4)
|
122
293
|
aws-sdk-cloudwatch (~> 1.6)
|
123
294
|
sidekiq (>= 5.0, < 8.0)
|
124
295
|
sys-uname (1.2.3)
|
125
296
|
ffi (~> 1.1)
|
126
|
-
|
297
|
+
thor (1.3.1)
|
298
|
+
timecop (0.9.8)
|
299
|
+
timeout (0.4.1)
|
300
|
+
typhoeus (1.4.1)
|
127
301
|
ethon (>= 0.9.0)
|
128
302
|
tzinfo (2.0.6)
|
129
303
|
concurrent-ruby (~> 1.0)
|
130
|
-
unicode-display_width (2.
|
304
|
+
unicode-display_width (2.5.0)
|
131
305
|
uri (0.13.0)
|
132
|
-
webmock (3.
|
306
|
+
webmock (3.23.0)
|
133
307
|
addressable (>= 2.8.0)
|
134
308
|
crack (>= 0.3.2)
|
135
309
|
hashdiff (>= 0.4.0, < 2.0.0)
|
136
|
-
|
310
|
+
webrick (1.8.1)
|
311
|
+
websocket-driver (0.7.6)
|
312
|
+
websocket-extensions (>= 0.1.0)
|
313
|
+
websocket-extensions (0.1.5)
|
314
|
+
zeitwerk (2.6.14)
|
137
315
|
|
138
316
|
PLATFORMS
|
139
317
|
ruby
|
@@ -141,6 +319,7 @@ PLATFORMS
|
|
141
319
|
x86_64-linux
|
142
320
|
|
143
321
|
DEPENDENCIES
|
322
|
+
activesupport (~> 7.1, >= 7.1.3.2)
|
144
323
|
factory_bot
|
145
324
|
faker
|
146
325
|
faraday
|
@@ -148,12 +327,16 @@ DEPENDENCIES
|
|
148
327
|
jwt (~> 1.5, >= 1.5.4)
|
149
328
|
learnosity-sdk (~> 0.2.2)
|
150
329
|
multi_json
|
330
|
+
rails (~> 7.1)
|
151
331
|
rake (~> 13.0)
|
152
|
-
rspec
|
332
|
+
rspec
|
333
|
+
rspec-rails (~> 6.1.0)
|
153
334
|
rubocop
|
154
335
|
sentry-ruby
|
336
|
+
sqlite3 (~> 1.4)
|
155
337
|
strongmind-oneroster-client (~> 2.0.3)
|
156
338
|
strongmind-platform-sdk!
|
339
|
+
timecop
|
157
340
|
webmock
|
158
341
|
|
159
342
|
BUNDLED WITH
|
data/README.md
CHANGED
@@ -11,7 +11,7 @@ First [configure your GitHub credentials](#configure-github-credentials)
|
|
11
11
|
Install the gem and add to the application's Gemfile by executing:
|
12
12
|
|
13
13
|
```
|
14
|
-
gem "strongmind-platform-sdk", "~> 3.
|
14
|
+
gem "strongmind-platform-sdk", "~> 3.19.1"
|
15
15
|
```
|
16
16
|
|
17
17
|
If bundler is not being used to manage dependencies, install the gem by executing:
|
@@ -67,9 +67,15 @@ gem push --key github --host https://rubygems.pkg.github.com/StrongMind platform
|
|
67
67
|
|
68
68
|
## Development
|
69
69
|
|
70
|
-
After checking out the repo, run `bin/setup` to install dependencies.
|
70
|
+
After checking out the repo, run `bin/setup` to install dependencies.
|
71
71
|
|
72
|
-
|
72
|
+
Migrate the database for the dummy app:
|
73
|
+
```
|
74
|
+
cd spec/dummy
|
75
|
+
RAILS_ENV=test rails db:migrate
|
76
|
+
```
|
77
|
+
|
78
|
+
Then, run `bundle exec rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
73
79
|
|
74
80
|
## Contributing
|
75
81
|
|
@@ -83,10 +89,123 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
83
89
|
|
84
90
|
Everyone interacting in the Platform::Ruby::Sdk project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/platform-ruby-sdk/blob/main/CODE_OF_CONDUCT.md).
|
85
91
|
|
86
|
-
##
|
92
|
+
## Data Pipeline Concern
|
93
|
+
|
94
|
+
The `DataPipelineable` concern is a shared concern that can be included in models
|
95
|
+
automatically to send data to the Data Pipeline on creates, updates, and destroys.
|
96
|
+
|
97
|
+
### Installation
|
98
|
+
Ensure that `platform-sdk` is required in the application.
|
99
|
+
|
100
|
+
One way to do this is to require the SDK via the `Gemfile`:
|
101
|
+
|
102
|
+
```ruby
|
103
|
+
gem 'strongmind-platform-sdk', require: 'platform_sdk'
|
104
|
+
```
|
105
|
+
|
106
|
+
This provides the application access to the `DataPipelineable` concern and RSpec shared examples.
|
107
|
+
|
108
|
+
### Usage
|
109
|
+
|
110
|
+
To use the `DataPipelineable` concern in a model, include the concern in the model:
|
111
|
+
|
112
|
+
```ruby
|
113
|
+
class MyModel < ApplicationRecord
|
114
|
+
include PlatformSdk::ActiveRecord::DataPipelineable
|
115
|
+
end
|
116
|
+
```
|
117
|
+
|
118
|
+
For the concern to function, the model must have both a `pipeline_noun` and a `pipeline_meta` class method that returns the noun and metadata of the model, respectively.
|
119
|
+
|
120
|
+
This can be done once by defining the method(s) in the ApplicationRecord class:
|
121
|
+
|
122
|
+
```ruby
|
123
|
+
class ApplicationRecord < ActiveRecord::Base
|
124
|
+
self.abstract_class = true
|
125
|
+
|
126
|
+
def self.pipeline_noun
|
127
|
+
"StrongMind.Central.#{name}}"
|
128
|
+
end
|
129
|
+
|
130
|
+
def self.pipeline_meta
|
131
|
+
{
|
132
|
+
"source": "strongmind-central"
|
133
|
+
}
|
134
|
+
end
|
135
|
+
end
|
136
|
+
```
|
137
|
+
|
138
|
+
Or it can be defined in each model:
|
139
|
+
|
140
|
+
```ruby
|
141
|
+
class MyModel < ApplicationRecord
|
142
|
+
include PlatformSdk::ActiveRecord::DataPipelineable
|
143
|
+
|
144
|
+
def self.pipeline_noun
|
145
|
+
"StrongMind.Central.#{name}}"
|
146
|
+
end
|
147
|
+
|
148
|
+
def self.pipeline_meta
|
149
|
+
{
|
150
|
+
"source": "strongmind-central"
|
151
|
+
}
|
152
|
+
end
|
153
|
+
end
|
154
|
+
```
|
155
|
+
|
156
|
+
You can override the following methods in the model to customize the noun data:
|
157
|
+
|
158
|
+
```ruby
|
159
|
+
class MyModel < ApplicationRecord
|
160
|
+
include PlatformSdk::ActiveRecord::DataPipelineable
|
161
|
+
|
162
|
+
def pipeline_excluded_attributes
|
163
|
+
[:column1, :column2]
|
164
|
+
end
|
165
|
+
|
166
|
+
def pipeline_additional_attributes
|
167
|
+
{
|
168
|
+
"foo": "important data",
|
169
|
+
"bar": "more important data"
|
170
|
+
}
|
171
|
+
end
|
172
|
+
end
|
173
|
+
```
|
174
|
+
|
175
|
+
### Configuration
|
176
|
+
You will need the following ENV variables set in your application to send data to the Data Pipeline (found in bitwarden):
|
177
|
+
* DATA_PIPELINE_HOST
|
178
|
+
* DATA_PIPELINE_USERNAME
|
179
|
+
* DATA_PIPELINE_PASSWORD
|
180
|
+
|
181
|
+
|
182
|
+
### Testing
|
183
|
+
|
184
|
+
To test the `DataPipelineable` concern for a model, include the common shared examples in the model's spec file:
|
185
|
+
|
186
|
+
```ruby
|
187
|
+
RSpec.describe MyModel, type: :model do
|
188
|
+
describe 'sends to the Data Pipeline' do
|
189
|
+
it_behaves_like 'DataPipelineable'
|
190
|
+
end
|
191
|
+
end
|
192
|
+
```
|
193
|
+
|
194
|
+
Make sure to stub the call to the Data Pipeline in `rails_helper.rb`
|
195
|
+
|
196
|
+
```ruby
|
197
|
+
config.before(:each) do
|
198
|
+
allow_any_instance_of(PlatformSdk::DataPipeline::Client).to receive(:post)
|
199
|
+
end
|
200
|
+
```
|
201
|
+
|
202
|
+
|
203
|
+
## Setting up IRB for API Client Testing
|
87
204
|
Require needed dependencies:
|
88
205
|
`require 'platform_sdk'`
|
89
206
|
|
207
|
+
|
208
|
+
### OneRoster API Client Initialization Example
|
90
209
|
Open IRB and initialize dependencies:
|
91
210
|
* IDENTITY_CLIENT_ID
|
92
211
|
* IDENTITY_CLIENT_SECRET
|
@@ -102,6 +221,7 @@ Create Identity Auth Client:
|
|
102
221
|
Create OneRoster Client:
|
103
222
|
`one_roster_client = PlatformSdk::OneRoster::Client.new(ONEROSTER_BASE_URL, auth_client)`
|
104
223
|
|
224
|
+
### Additional Client Initialization Examples
|
105
225
|
Create Aws Client:
|
106
226
|
`aws_client = PlatformSdk::Aws::SecretsManagerClient.new(access_key_id: 'ACCESS_KEY_ID', secret_access_key: 'SECRET_ACCESS_KEY', region: 'REGION')`
|
107
227
|
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
module PlatformSdk
|
4
|
+
module ActiveRecord
|
5
|
+
|
6
|
+
module DataPipelineable
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
after_create -> { send_to_pipeline('created') }
|
11
|
+
before_destroy -> { send_to_pipeline('destroyed') }
|
12
|
+
after_update -> { send_to_pipeline('modified') }
|
13
|
+
end
|
14
|
+
|
15
|
+
def pipeline_payload(action)
|
16
|
+
{
|
17
|
+
"noun": self.class.pipeline_noun,
|
18
|
+
"identifiers": pipeline_identifiers,
|
19
|
+
"meta": self.class.pipeline_meta,
|
20
|
+
"data": pipeline_data(action),
|
21
|
+
"envelope_version": '1.0.0',
|
22
|
+
"message_timestamp": Time.current.utc.iso8601
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.pipeline_noun
|
27
|
+
raise NotImplementedError, 'You must implement the pipeline_noun class method'
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.pipeline_meta
|
31
|
+
raise NotImplementedError, 'You must implement the pipeline_meta class method, an example value is { "source": "strongmind-central" }'
|
32
|
+
end
|
33
|
+
|
34
|
+
def pipeline_excluded_attributes
|
35
|
+
[]
|
36
|
+
end
|
37
|
+
|
38
|
+
def pipeline_identifiers
|
39
|
+
{
|
40
|
+
"id": id
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
def pipeline_data(action)
|
45
|
+
data_hash = { action: }.merge!(attributes.symbolize_keys)
|
46
|
+
|
47
|
+
data_hash.merge!(pipeline_additional_attributes)
|
48
|
+
|
49
|
+
data_hash.except(*pipeline_excluded_attributes)
|
50
|
+
end
|
51
|
+
|
52
|
+
def pipeline_additional_attributes
|
53
|
+
{}
|
54
|
+
end
|
55
|
+
|
56
|
+
def one_roster_pipeline_payload(deleted: false)
|
57
|
+
{}
|
58
|
+
end
|
59
|
+
|
60
|
+
def send_to_pipeline(action)
|
61
|
+
credentials = {
|
62
|
+
pipeline_host: ENV.fetch('DATA_PIPELINE_HOST', 'stage-di-data-pipeline-api.strongmind.com'),
|
63
|
+
pipeline_username: ENV.fetch('DATA_PIPELINE_USERNAME', 'canvas_prod'),
|
64
|
+
pipeline_password: ENV.fetch('DATA_PIPELINE_PASSWORD', '')
|
65
|
+
}
|
66
|
+
client = PlatformSdk::DataPipeline::Client.new(credentials)
|
67
|
+
client.post(pipeline_payload(action)) unless Rails.env.development?
|
68
|
+
return unless respond_to?(:one_roster_data_type) && !Rails.env.development?
|
69
|
+
|
70
|
+
client.post(one_roster_pipeline_payload(deleted: action == "destroyed"))
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -17,6 +17,7 @@ module PlatformSdk
|
|
17
17
|
faraday.request(:retry, retry_options)
|
18
18
|
faraday.request(:authorization, :basic, @credentials[:pipeline_username], @credentials[:pipeline_password])
|
19
19
|
faraday.headers = headers
|
20
|
+
faraday.response :raise_error
|
20
21
|
faraday.adapter(:net_http)
|
21
22
|
end
|
22
23
|
end
|
@@ -39,6 +39,8 @@ module PlatformSdk
|
|
39
39
|
|
40
40
|
def with_rescue
|
41
41
|
yield
|
42
|
+
rescue Faraday::TimeoutError => e
|
43
|
+
raise TimeoutError, e
|
42
44
|
rescue Faraday::ServerError => e
|
43
45
|
raise_error_with_payload(ServerError, e)
|
44
46
|
rescue Faraday::ClientError => e
|
@@ -77,20 +79,6 @@ module PlatformSdk
|
|
77
79
|
Time.at(JWT.decode(jwt, nil, false)[0]["exp"])
|
78
80
|
end
|
79
81
|
|
80
|
-
def refresh_token_if_expired(jwt:, refresh_token:)
|
81
|
-
raise ArgumentError if refresh_token.nil? || jwt.nil?
|
82
|
-
return unless token_expired?(jwt)
|
83
|
-
|
84
|
-
refresh_token(refresh_token)
|
85
|
-
end
|
86
|
-
|
87
|
-
def refresh_token(refresh_token)
|
88
|
-
raise ArgumentError if refresh_token.nil?
|
89
|
-
|
90
|
-
post_payload("/connect/token", request_body(
|
91
|
-
grant_type: "refresh_token", refresh_token:))
|
92
|
-
end
|
93
|
-
|
94
82
|
def refresh_session(session: {})
|
95
83
|
raise ArgumentError if session[:access_token].nil? || session[:refresh_token].nil?
|
96
84
|
|
@@ -103,6 +91,19 @@ module PlatformSdk
|
|
103
91
|
session[:refresh_token] = refreshed_tokens[:refresh_token]
|
104
92
|
end
|
105
93
|
|
94
|
+
def refresh_token_if_expired(jwt:, refresh_token:)
|
95
|
+
raise ArgumentError if refresh_token.nil? || jwt.nil?
|
96
|
+
return unless token_expired?(jwt)
|
97
|
+
|
98
|
+
new_refresh_token(refresh_token)
|
99
|
+
end
|
100
|
+
|
101
|
+
def new_refresh_token(refresh_token)
|
102
|
+
raise ArgumentError if refresh_token.nil?
|
103
|
+
|
104
|
+
post_payload("/connect/token", request_body(grant_type: "refresh_token", refresh_token:))
|
105
|
+
end
|
106
|
+
|
106
107
|
def raise_error_with_payload(exception_class, error)
|
107
108
|
json_log = {
|
108
109
|
exception: exception_class.new.class.name.demodulize,
|
@@ -110,7 +111,7 @@ module PlatformSdk
|
|
110
111
|
response_body: error.response[:body],
|
111
112
|
status: error.response[:status]
|
112
113
|
}.compact
|
113
|
-
Rails.logger.info json_log.to_json if
|
114
|
+
Rails.logger.info json_log.to_json if defined?(Rails)
|
114
115
|
raise exception_class, error.response
|
115
116
|
end
|
116
117
|
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module PlatformSdk
|
2
|
+
module SpecSupport
|
3
|
+
RSpec.shared_examples "DataPipelineable" do
|
4
|
+
let(:data) do
|
5
|
+
{ action: }
|
6
|
+
.merge(record.attributes.symbolize_keys)
|
7
|
+
.merge(record.pipeline_additional_attributes)
|
8
|
+
.except(*record.pipeline_excluded_attributes)
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:pipeline_payload) do
|
12
|
+
{
|
13
|
+
"noun": described_class.pipeline_noun,
|
14
|
+
"identifiers": { "id": record.id },
|
15
|
+
"meta": described_class.pipeline_meta,
|
16
|
+
"data": data,
|
17
|
+
"envelope_version": '1.0.0',
|
18
|
+
"message_timestamp": Time.current.utc.iso8601
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
let(:record) { build(described_class.to_s.underscore.to_sym) }
|
23
|
+
let(:data_pipeline_client) { double(PlatformSdk::DataPipeline::Client)}
|
24
|
+
|
25
|
+
before do
|
26
|
+
allow(PlatformSdk::DataPipeline::Client).to receive(:new).and_return(data_pipeline_client)
|
27
|
+
allow(data_pipeline_client).to receive(:post)
|
28
|
+
Timecop.freeze(DateTime.parse('2024-06-09 04:20:00'))
|
29
|
+
end
|
30
|
+
|
31
|
+
after do
|
32
|
+
Timecop.return
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'after_create callbacks' do
|
36
|
+
let(:action) { 'created' }
|
37
|
+
|
38
|
+
it "defines an after_create callback" do
|
39
|
+
record.save!
|
40
|
+
expect(data_pipeline_client).to have_received(:post).with(pipeline_payload)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'before_destroy callbacks' do
|
45
|
+
let(:action) { 'destroyed' }
|
46
|
+
|
47
|
+
it "defines an after_destroy callback" do
|
48
|
+
record.save!
|
49
|
+
record.destroy
|
50
|
+
expect(data_pipeline_client).to have_received(:post).with(pipeline_payload)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'after_update callbacks' do
|
55
|
+
let(:action) { 'modified' }
|
56
|
+
|
57
|
+
it "defines an after_update callback" do
|
58
|
+
record.save!
|
59
|
+
column = column_to_update(record)
|
60
|
+
update_record(record, column)
|
61
|
+
expect(data_pipeline_client).to have_received(:post).with(pipeline_payload)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def column_to_update(record)
|
66
|
+
[:string, :integer, :boolean].each do |type|
|
67
|
+
if record.class.columns.select { |c| c.sql_type_metadata.type == type && !c.name.match?(/_type$/) }.any?
|
68
|
+
return record.class.columns.select { |c| c.sql_type_metadata.type == type && !c.name.match?(/_type$/) }.first.name
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def update_record(record, column)
|
74
|
+
new_record = build(described_class.to_s.underscore.to_sym)
|
75
|
+
|
76
|
+
column_class = record[column]
|
77
|
+
case column_class
|
78
|
+
when String
|
79
|
+
record.update!(column => new_record[column])
|
80
|
+
when Integer
|
81
|
+
record.update!(column => 69)
|
82
|
+
when Boolean
|
83
|
+
record.update!(column => !record[column])
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PlatformSdk
|
4
|
+
module SpecSupport
|
5
|
+
RSpec.shared_examples "OneRosterDataPipelineable" do |record_keys|
|
6
|
+
let(:data) do
|
7
|
+
record_keys.each_with_object({}) do |key, hash|
|
8
|
+
if key == "_type"
|
9
|
+
hash[:type] = record.try(key)
|
10
|
+
next
|
11
|
+
end
|
12
|
+
hash[key.to_sym] = record.try(key)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
let(:pipeline_payload) do
|
16
|
+
{
|
17
|
+
"noun": "StrongMind.Platform.OneRoster.#{record.one_roster_data_type.capitalize}",
|
18
|
+
"identifiers": { "sourcedId": record.roster_id },
|
19
|
+
"meta": {
|
20
|
+
"version": "3",
|
21
|
+
"source": "Central OneRoster API"
|
22
|
+
},
|
23
|
+
"data": one_roster_common_data.merge!(data),
|
24
|
+
"envelope_version": "1.0.0",
|
25
|
+
"message_timestamp": Time.current.utc.iso8601
|
26
|
+
}
|
27
|
+
end
|
28
|
+
let(:record) { build(described_class.to_s.underscore.to_sym) }
|
29
|
+
let(:one_roster_common_data) do
|
30
|
+
{
|
31
|
+
"sourcedId": record.roster_id,
|
32
|
+
"status": record.status,
|
33
|
+
"dateLastModified": record.updated_at,
|
34
|
+
"metadata": record.metadata
|
35
|
+
}
|
36
|
+
end
|
37
|
+
let(:data_pipeline_client) { double(PlatformSdk::DataPipeline::Client) }
|
38
|
+
|
39
|
+
before do
|
40
|
+
allow(PlatformSdk::DataPipeline::Client).to receive(:new).and_return(data_pipeline_client)
|
41
|
+
allow(data_pipeline_client).to receive(:post)
|
42
|
+
Timecop.freeze(DateTime.parse("2024-06-09 04:20:00"))
|
43
|
+
end
|
44
|
+
|
45
|
+
after do
|
46
|
+
Timecop.return
|
47
|
+
end
|
48
|
+
|
49
|
+
context "after_create callbacks" do
|
50
|
+
let(:action) { "created" }
|
51
|
+
|
52
|
+
it "defines an after_create callback" do
|
53
|
+
record.save!
|
54
|
+
expect(data_pipeline_client).to have_received(:post).with(pipeline_payload)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context "before_destroy callbacks" do
|
59
|
+
let(:action) { "destroyed" }
|
60
|
+
let(:one_roster_common_data_deleted) do
|
61
|
+
one_roster_common_data.merge(
|
62
|
+
"status": "tobedeleted"
|
63
|
+
)
|
64
|
+
end
|
65
|
+
|
66
|
+
let(:pipeline_payload_deleted) do
|
67
|
+
pipeline_payload.merge("data": one_roster_common_data_deleted)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "defines an after_destroy callback" do
|
71
|
+
record.save!
|
72
|
+
record.destroy
|
73
|
+
expect(data_pipeline_client).to have_received(:post).with(pipeline_payload)
|
74
|
+
expect(data_pipeline_client).to have_received(:post).with(pipeline_payload_deleted)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context "after_update callbacks" do
|
79
|
+
let(:action) { "modified" }
|
80
|
+
|
81
|
+
it "defines an after_update callback" do
|
82
|
+
record.save!
|
83
|
+
column = column_to_update(record)
|
84
|
+
update_record(record, column)
|
85
|
+
expect(data_pipeline_client).to have_received(:post).with(pipeline_payload)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def column_to_update(record)
|
90
|
+
%i[string integer boolean].each do |type|
|
91
|
+
if record.class.columns.select { |c| c.sql_type_metadata.type == type && !c.name.match?(/_type$/) }.any?
|
92
|
+
return record.class.columns.select { |c| c.sql_type_metadata.type == type && !c.name.match?(/_type$/) }.first.name
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def update_record(record, column)
|
98
|
+
column_class = record[column]
|
99
|
+
case column_class
|
100
|
+
when String
|
101
|
+
record.update!(column => "new value")
|
102
|
+
when Integer
|
103
|
+
record.update!(column => 69)
|
104
|
+
when Boolean
|
105
|
+
record.update!(column => !record[column])
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rspec/core'
|
4
|
+
require 'platform_sdk/spec_support/shared_examples/data_pipelineable_examples'
|
5
|
+
require 'platform_sdk/spec_support/shared_examples/one_roster_data_pipelineable_examples'
|
6
|
+
|
7
|
+
module PlatformSdk
|
8
|
+
module SpecSupport
|
9
|
+
end
|
10
|
+
end
|
data/lib/platform_sdk/version.rb
CHANGED
data/lib/platform_sdk.rb
CHANGED
@@ -16,6 +16,8 @@ require "platform_sdk/canvas_api"
|
|
16
16
|
require "platform_sdk/bynder"
|
17
17
|
require "platform_sdk/events"
|
18
18
|
require "platform_sdk/central"
|
19
|
+
require "platform_sdk/active_record/data_pipelineable"
|
20
|
+
require "platform_sdk/spec_support"
|
19
21
|
|
20
22
|
module PlatformSdk
|
21
23
|
class Error < StandardError; end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: strongmind-platform-sdk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.19.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Platform Team
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-05-
|
11
|
+
date: 2024-05-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -156,6 +156,34 @@ dependencies:
|
|
156
156
|
- - ">="
|
157
157
|
- !ruby/object:Gem::Version
|
158
158
|
version: '0'
|
159
|
+
- !ruby/object:Gem::Dependency
|
160
|
+
name: activesupport
|
161
|
+
requirement: !ruby/object:Gem::Requirement
|
162
|
+
requirements:
|
163
|
+
- - "~>"
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '7.1'
|
166
|
+
type: :runtime
|
167
|
+
prerelease: false
|
168
|
+
version_requirements: !ruby/object:Gem::Requirement
|
169
|
+
requirements:
|
170
|
+
- - "~>"
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
version: '7.1'
|
173
|
+
- !ruby/object:Gem::Dependency
|
174
|
+
name: rails
|
175
|
+
requirement: !ruby/object:Gem::Requirement
|
176
|
+
requirements:
|
177
|
+
- - "~>"
|
178
|
+
- !ruby/object:Gem::Version
|
179
|
+
version: '7.1'
|
180
|
+
type: :development
|
181
|
+
prerelease: false
|
182
|
+
version_requirements: !ruby/object:Gem::Requirement
|
183
|
+
requirements:
|
184
|
+
- - "~>"
|
185
|
+
- !ruby/object:Gem::Version
|
186
|
+
version: '7.1'
|
159
187
|
description: Includes a wrapper for the swagger generated OneRoster management clients
|
160
188
|
email:
|
161
189
|
- horseshoes@strongmind.com
|
@@ -177,6 +205,7 @@ files:
|
|
177
205
|
- Rakefile
|
178
206
|
- docs/identity_installation_in_rails.md
|
179
207
|
- lib/platform_sdk.rb
|
208
|
+
- lib/platform_sdk/active_record/data_pipelineable.rb
|
180
209
|
- lib/platform_sdk/aws.rb
|
181
210
|
- lib/platform_sdk/aws/secrets_manager_client.rb
|
182
211
|
- lib/platform_sdk/bynder.rb
|
@@ -215,6 +244,9 @@ files:
|
|
215
244
|
- lib/platform_sdk/power_school/client.rb
|
216
245
|
- lib/platform_sdk/power_school/special_program.rb
|
217
246
|
- lib/platform_sdk/sentry.rb
|
247
|
+
- lib/platform_sdk/spec_support.rb
|
248
|
+
- lib/platform_sdk/spec_support/shared_examples/data_pipelineable_examples.rb
|
249
|
+
- lib/platform_sdk/spec_support/shared_examples/one_roster_data_pipelineable_examples.rb
|
218
250
|
- lib/platform_sdk/version.rb
|
219
251
|
- sig/platform_sdk/identity/auth_client.rbs
|
220
252
|
- sig/platform_sdk/learnosity_api/client.rbs
|