skn_utils 5.4.0 → 5.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +5 -5
  2. data/.rspec +2 -0
  3. data/README.md +223 -72
  4. data/_config.yml +4 -4
  5. data/bin/concurrent_test_block +54 -0
  6. data/bin/concurrent_test_grouped +45 -0
  7. data/bin/concurrent_test_procs +45 -0
  8. data/bin/concurrent_test_wrapped +49 -0
  9. data/lib/skn_container.rb +2 -1
  10. data/lib/skn_failure.rb +2 -0
  11. data/lib/skn_hash.rb +2 -0
  12. data/lib/skn_registry.rb +25 -5
  13. data/lib/skn_settings.rb +2 -0
  14. data/lib/skn_success.rb +2 -0
  15. data/lib/skn_utils.rb +13 -2
  16. data/lib/skn_utils/concurrent_jobs.rb +117 -0
  17. data/lib/skn_utils/configurable.rb +55 -6
  18. data/lib/skn_utils/configuration.rb +2 -0
  19. data/lib/skn_utils/core_extensions.rb +29 -0
  20. data/lib/skn_utils/dotted_hash.rb +1 -0
  21. data/lib/skn_utils/env_string_handler.rb +2 -0
  22. data/lib/skn_utils/http_processor.rb +34 -0
  23. data/lib/skn_utils/job_commands.rb +247 -0
  24. data/lib/skn_utils/nested_result.rb +2 -0
  25. data/lib/skn_utils/notifier_base.rb +2 -0
  26. data/lib/skn_utils/null_object.rb +2 -0
  27. data/lib/skn_utils/page_controls.rb +2 -0
  28. data/lib/skn_utils/result_bean.rb +2 -0
  29. data/lib/skn_utils/version.rb +3 -1
  30. data/lib/skn_utils/wrappable.rb +32 -0
  31. data/skn_utils.gemspec +27 -22
  32. data/spec/lib/skn_utils/concurrent_jobs_spec.rb +279 -0
  33. data/spec/lib/skn_utils/configurable_spec.rb +23 -36
  34. data/spec/lib/skn_utils/registry_spec.rb +22 -0
  35. data/spec/lib/skn_utils/wrappers_spec.rb +80 -0
  36. data/spec/spec_helper.rb +5 -0
  37. data/spec/support/configurables.rb +36 -0
  38. data/spec/support/xml_matchers.rb +121 -0
  39. metadata +71 -24
  40. data/README.rdoc +0 -379
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: faaa010ea403a5bfbf20386ee86a9c68e8982da1
4
- data.tar.gz: 909be6bef4b46a41bfd293d35a3059396d4adba5
2
+ SHA256:
3
+ metadata.gz: bdbe2b2318e4841c25afdec1e118cc19ff445f8a8b1e08d116715f5b9df0f56e
4
+ data.tar.gz: d42c5e55def5f8c2789714d1fada2f341f59665ba633192732b9e6b48816e253
5
5
  SHA512:
6
- metadata.gz: 46f92868aaecee7ece92b3d1c4b5bc33b5643e8c2de3a5f442e5141edb2b45d5a4cb8d4bd29e24241a34001b253abec38fe381e8ca8d798dc8eb6d662fdc12c2
7
- data.tar.gz: 81c41c8dda9b50797a76005a29cb329b2d8bc9da0af585d1848124a54606ac1f3a9d8bb8bb1d6ec5b2806df0002d673849425ca68290121e4ac327c7b94f784d
6
+ metadata.gz: b48e34a868729ed2fe63cc77c456a9b9eef99540355d4de6135c7cd5fe96c88b78519cc8384f2eb13c0a29b9652b4e84fbc1624a4674df0ec73c4f95d3762392
7
+ data.tar.gz: c435de19604f41834446ca04084ffc7a559267786974130edc03ad2a540f07eb08111571b13995f67e6bcfc122b215a3d5bb5cf26a905d1e3e85b31e4f0dfad3
data/.rspec CHANGED
@@ -1,2 +1,4 @@
1
1
  --color
2
2
  --require spec_helper
3
+ --format html
4
+ --out coverage/rspec_results.html
data/README.md CHANGED
@@ -2,68 +2,94 @@
2
2
  [![Gem Version](https://badge.fury.io/rb/skn_utils.svg)](http://badge.fury.io/rb/skn_utils)
3
3
 
4
4
  # SknUtils
5
- ## SknUtils::NestedResult class; dynamic key/value container
6
- A Ruby Gem containing a Ruby PORO (Plain Old Ruby Object) that can be instantiated at runtime with an input hash. This library creates
7
- an Object with Dot and Hash notational accessors to each key's value. Additional key/value pairs can be added post-create
8
- by simply assigning it; `obj.my_new_var = "some value"`
9
-
10
- * Transforms the initialing hash into accessible object instance values, with their keys as method names.
11
- * If the key's value is also a hash, it too will become an Object.
12
- * if the key's value is a Array of Hashes, or Array of Arrays of Hashes, each hash element of the Arrays will become an Object.
13
- * The current key/value (including nested) pairs are returned via #to_hash or #to_json when and if needed.
14
- * Best described as dot notation wrapper over a Ruby (Concurrent-Ruby) Hash.
15
5
 
16
- Ruby's Hash object is already extremely flexible, even more so with the addition of dot-notation. As I work more with Ruby outside of Rails, I'm finding more use cases for the capabilities of this gem. Here are a few examples:
17
-
18
- 1. Application settings containers, SknSettings. Loads Yaml file based on `ENV['RACK_ENV']` value, or specified file-key.
19
- - Replaces Config and/or RBConfig Gems for yaml based settings
20
- 1. Substitute for Rails.root, via a little ERB/YAML/Marshal statement in settings.yml file, and a helper class
21
- - settings.yml (YAML)
22
- - `root: <%= Dir.pwd %>`
23
- - enables `SknSettings.root`
24
- - `env: !ruby/string:SknUtils::EnvStringHandler <%= ENV.fetch('RACK_ENV', 'development') %>`
25
- - enables `SknSettings.env.production?` ...
26
- 1. Since SknSettings is by necessity a global constant, it can serve as Session Storage to keep system objects; like a ROM-RB instance.
27
- 1. In-Memory Key-Store, use it to cache active user objects, or active Integration passwords, and/or objects that are not serializable.
28
- 1. Command registries used to dispatch command requests to proper command handler. see example app [SknBase](https://github.com/skoona/skn_base/blob/master/strategy/services/content/command_handler.rb)
29
- ```ruby
30
- SknSettings.command_handler = {
31
- Commands::RetrieveAvailableResources => method(:resources_metadata_service),
32
- Commands::RetrieveResourceContent => method(:resource_content_service)
33
- }
34
- ...
35
- SknSettings.command_handler[ cmd.class ].call( cmd )
36
- -- or --
37
- SknSettings.command_handler.key?( cmd.class ) && cmd.valid? ?
38
- SknSettings.command_handler[ cmd.class ].call( cmd ) : command_not_found_action()
39
- ```
40
- There are many more use cases for Ruby's Hash that this gem just makes easier to implement.
41
-
42
-
43
- ## Available Classes
44
- * SknSuccess
45
- * SknFailure
6
+ `SknUtils` is a collection of pure-ruby utility classes and modules, with limited
7
+ dependencies, to augment the development of Ruby applications. Examples of these
8
+ utilities in action can be found in my related projects `SknServices`, `SknWebApp`,
9
+ and `SknBase`.
10
+
11
+ * Most classes are standalone modules, or cleary documented, and can be copy/pasted into your project.
12
+ * The exchange or handoff of values between objects is addressed via the `NestedResults`
13
+ class which implements dot-notation and nesting over a concurrent hash: A ruby Hash can
14
+ use any valid ruby object as a key or value.
15
+ * `NestedResults` is later sub-classed as `Configuration` to provide application level
16
+ settings using YAML files with a API simular to the RbConfig gem.
17
+ * Object or method return values can be enclosed in `SknSuccess` or `SknFailure` classes
18
+ to prevent or minimize nil returns.
19
+ * Precise microsecond `duration`s, Number to `as_human_size`, and a `catch_exceptions`
20
+ retry-able feature are implemented on the SknUtils class directly for ease of use.
21
+ * `Configurable` module extends any class or module with configurable attribute method
22
+ as needed, with a set of defaults methods which emulate Rails.env, Rails.logger, and
23
+ Rails.root functionality.
24
+ * `CoreObjectExtensions` simular to ActiveSupport's, `#present?` and `#blank?` are
25
+ automatically applied, unless already present, when SknUtils gem is loaded.
26
+ * `SknRegistry` class is an advanced feature which allows you to manually register
27
+ classes, procs, or any value with a user-defined `label`. Initialization and dependency injection
28
+ requirements of service-like classes can be included in this registration process allowing
29
+ them to be centrally maintained. The `label` can be any valid ruby value; like a
30
+ classname, symbol, or string as needed
31
+ * `NullObject`, `NotifierBase`, and `Wrappable` are interesting classes which you might want to explore further.
32
+ * `ConcurrentJobs` is a feature implemented to allow concurrent/multi-threaded execution of jobs. The included
33
+ companion classes focus on HTTP GET,PUT,POST, and DELETE jobs as an example of how to use the `ConcurrentJobs` feature.
34
+
35
+ All classes and modules have RSpec test coverage (90+) of their originally intended
36
+ use-cases.
37
+
38
+
39
+ ### Available Classes
46
40
  * SknSettings
47
41
  * SknUtils::Configuration
48
42
  * SknUtils::EnvStringHandler
49
- * SknRegistry
50
- * SknContainer
51
43
  * SknHash
52
44
  * SknUtils::ResultBean
53
45
  * SknUtils::PageControls
54
46
  * SknUtils::NestedResult
55
- * SknUtils::NullObject
56
- * SknUtils::CoreObjectExtensions
47
+ * SknRegistry
48
+ * SknContainer
49
+ * SknSuccess
50
+ * SknFailure
57
51
  * SknUtils::Configurable
58
-
59
- ## Available Class.Methods
52
+ * SknUtils::CoreObjectExtensions
53
+ * SknUtils::NullObject
54
+ * SknUtils::NotifierBase
55
+ * SknUtils::Wrappable
56
+ * SknUtils::ConcurrentJobs
57
+ * SknUtils::JobWrapper (via ConcurrentJobs)
58
+ * SknUtils::CommandJSONPost (via JobCommands)
59
+ * SknUtils::CommandFORMPost
60
+ * SknUtils::CommandJSONGet
61
+ * SknUtils::CommandJSONPut
62
+ * SknUtils::CommandFORMDelete
63
+ * SknUtils::HttpProcessor
64
+
65
+ ### Available Class.Methods
60
66
  * SknUtils.catch_exceptions()
61
67
  * SknUtils.as_human_size()
62
68
  * SknUtils.duration(start_time=nil)
63
69
 
64
-
70
+ ### Available RSpec Helpers
71
+ * spec/support/xml_matchers.rb
72
+ * expect(bundle).to have_xpath('//witnesses/witness/role')
73
+ * expect(bundle).to have_nodes('//witnesses/witness/role', 3)
74
+ * expect(bundle).to match_xpath('//lossInformation/date', "2020-01-28")
75
+
65
76
 
66
77
  ## History
78
+ 2/3/2020 V5.7.0
79
+ Added
80
+ * RSpec XML_Matchers to spec/support folders
81
+ * Update ConcurrentJobs JobCommands to support HTTP Headers
82
+
83
+ 2/24/2019 V5.5.0
84
+ Added
85
+ * ConcurrentJobs feature set
86
+ - Executes (HTTP/any) jobs in parallel
87
+
88
+ 1/2/2019 V5.4.1
89
+ Added
90
+ - Wrappable module for evaluation.
91
+ - Ruby comment # frozen_string_literal, everywhere
92
+
67
93
  12/16/2018 V5.4.0
68
94
  Added :duration() utils to SknUtils module:
69
95
  #duration() #=> returns start_time value
@@ -154,27 +180,66 @@ There are many more use cases for Ruby's Hash that this gem just makes easier to
154
180
  06/2015 V1.5.1 commit #67ef656
155
181
  Last Version to depend on Rails (ActiveModel) for #to_json and #to_xml serialization
156
182
 
183
+ ### NestedResult class; dynamic key/value container
184
+ A class implementing a Ruby PORO (Plain Old Ruby Object) that can be instantiated at runtime with a hash. Creates
185
+ a nested object with Dot and Hash notational accessors to each key's value. Additional key/value pairs can be added post-create
186
+ by simply assigning it; `obj.my_new_var = "some value"`
187
+
188
+ * Transforms the initialing hash into accessible object instance values, with their keys as method names.
189
+ * If the key's value is also a hash, it too will become an Object.
190
+ * if the key's value is a Array of Hashes, or Array of Arrays of Hashes, each hash element of the Arrays will become an Object.
191
+ * The current key/value (including nested) pairs are returned via #to_hash or #to_json when and if needed.
192
+ * Best described as dot notation wrapper over a Ruby (Concurrent-Ruby) Hash.
193
+
194
+ Ruby's Hash object is already extremely flexible, even more so with the addition of dot-notation. As I work more with Ruby outside of Rails, I'm finding more use cases for the capabilities of this gem. Here are a few examples:
195
+
196
+ 1. Application settings containers, SknSettings. Loads Yaml file based on `ENV['RACK_ENV']` value, or specified file-key.
197
+ - Replaces Config and/or RBConfig Gems for yaml based settings
198
+ 1. Substitute for Rails.root, via a little ERB/YAML/Marshal statement in settings.yml file, and a helper class
199
+ - settings.yml (YAML)
200
+ - `root: <%= Dir.pwd %>`
201
+ - enables `SknSettings.root`
202
+ - `env: !ruby/string:SknUtils::EnvStringHandler <%= ENV.fetch('RACK_ENV', 'development') %>`
203
+ - enables `SknSettings.env.production?` ...
204
+
205
+ There are many more use cases for Ruby's Hash that this gem just makes easier to implement.
206
+
157
207
 
158
208
  ## Public Components
159
209
  SknUtils::NestedResult # Primary Key/Value Container with Dot/Hash notiation support.
160
- SknHash # Wrapper for name only, WITHOUT SknUtils namespace, inherits from SknUtils::NestedResult
161
- SknUtils::ResultBean # Wrapper for name only, inherits from SknUtils::NestedResult
162
- SknUtils::PageControls # Wrapper for name only, inherits from SknUtils::NestedResult
163
- SknUtils::DottedHash # Wrapper for name only, inherits from SknUtils::NestedResult
210
+ SknHash # Wrapper in name only, WITHOUT SknUtils namespace, inherits from SknUtils::NestedResult
211
+ SknUtils::ResultBean # Wrapper in name only, inherits from SknUtils::NestedResult
212
+ SknUtils::PageControls # Wrapper in name only, inherits from SknUtils::NestedResult
213
+ SknUtils::DottedHash # Wrapper in name only, inherits from SknUtils::NestedResult
164
214
 
165
- SknUtils::Configurable # Basic one-level class configuration Module
215
+ SknSettings # Multi-level application Configuration class, Key/Value Container with Dot/Hash notiation support.
216
+ - Reads YAML files from ./config/ directory based by environment (RACK_ENV)
217
+ - INITIALIZED WHEN GEM LOADS
166
218
 
167
- SknSettings # Multi-level application Configuration class, Key/Value Container with Dot/Hash notiation support.
219
+ SknUtils::Configurable # Add Class writers/getters to any Class, think class configuration
168
220
 
169
- SknContainer/SknRegistry # Basic Key/Value container which #registers and #resolves procs, classes, and/or object
221
+ SknContainer/SknRegistry # Key/Value container which #registers and #resolves procs, classes, and/or object
222
+ - Allows definition in one place, and label references as needed; dependency injection
223
+ - INITIALIZED WHEN GEM LOADS
170
224
 
171
- SknSuccess # Three attribute value containers for return codes -- #value, #message, #success
225
+ SknSuccess # Three attribute value containers for consistant return codes -- #value, #message, #success
172
226
  - Extra #payload method returns value as NestResult if value is_a Hash
173
227
  SknFailure # Three attribute value containers for return codes -- #value, #message, #success
228
+
229
+ SknUtils::ConcurrentJobs # Async/Sync Job executor pool with HTTP support
230
+ SknUtils::CommandJSONGet # HTTP Get Command class expecting `json` return, located inside `job_commands`
231
+ SknUtils::CommandJSONPut # HTTP Put Command class expecting `json` return, located inside `job_commands`
232
+ SknUtils::CommandJSONPost # HTTP Post Command class expecting `json` return, located inside `job_commands`
233
+ SknUtils::CommandFORMPost # HTTP Post Command class expecting `form` data return, located inside `job_commands`
234
+ SknUtils::CommandFORMDelete # HTTP Delete Command class expecting `form` data return, located inside `job_commands`
235
+ SknUtils::HttpProcessor # Command driven HTTP processing object supporting GET,PUT,POST, and DELETE
236
+ SknUtils::JobWrapper # Outer wrapper class to capture catastrophic exceptions (syntax normally)
174
237
 
175
238
 
176
239
  ## Public Methods: SknUtils::Configurable module
177
- For making an arbitrary class configurable and then specifying those configuration values.
240
+ For making an arbitrary class configurable and then specifying those configuration values. Intended to be used at the application
241
+ level, similar to the use of `Rails`, or for classes that would benefit from a configuration value when objects are created from it.
242
+
178
243
  ```ruby
179
244
  # (1) First establish the method names of class values desired.
180
245
  ################
@@ -239,21 +304,27 @@ There are many more use cases for Ruby's Hash that this gem just makes easier to
239
304
  ```
240
305
 
241
306
 
242
- ## Public Methods: SknContainer ONLY
243
- SknContainer is global constant assigned to an instantiated instance of SknRegistry.
244
- Returns the keyed value as the original instance/value or if provided a proc the result of calling that proc.
245
- To register a class or object for global retrieval, use the following API. Also review the RSpecs for additional useage info.
307
+ ## Public Methods: SknContainer and/or SknRegistry class
308
+ `SknContainer` is global constant assigned to an instantiated instance of `SknRegistry`. `SknRegistry` can
309
+ be instantiated in the regular way via `SknRegistry.new`; and is included in the SknConfigurable root options
310
+ by default under the key `registry`.
311
+
312
+ Either returns the labeled value as the original instance/value or if provided with a proc, the result of calling that proc.
313
+ To register, and `label`, a class or object for retrieval, use the following API. Also review the RSpecs for
314
+ additional useage info.
246
315
 
247
316
  #register(key, contents = nil, options = {})
248
317
  - example:
249
318
  SknContainer.register(:some_klass, MyClass) -- class as value
250
319
  SknContainer.register(:the_instance, MyClass.new) -- Object Instance as value
251
- SknContainer.register(:unique_instance, -> {MyClass.new}) -- New Object Instance for each #resolve
320
+ SknContainer.register(:unique_instance, -> {MyClass.new}, call: true) -- New Object Instance for each #resolve
321
+ SknContainer.register(:unique_instance2, ->(parms) {MyClass.new(parms)}, call: false) -- New Object with parms for each #resolve
322
+ SknContainer.register(:some_proc, -> {MyClass.new}, call: false) -- Return uncalled proc for each #resolve
252
323
 
253
324
  SknContainer -- #register returns self to enable chaining
254
325
  .register(:unique_instance, -> {MyClass.new})
255
- .register(:the_instance, MyClass.new)
256
- .register(:some_klass, MyClass)
326
+ .register(:the_instance, MyClass.new)
327
+ .register(:some_klass, MyClass)
257
328
 
258
329
  #resolve(key)
259
330
  - example:
@@ -261,15 +332,84 @@ There are many more use cases for Ruby's Hash that this gem just makes easier to
261
332
  instance = SknContainer.resolve(:some_klass).new
262
333
 
263
334
  obj_instance1 = SknContainer.resolve(:unique_instance)
264
- obj_instance2 = SknContainer.resolve(:unique_instance)
335
+ obj_instance2 = SknContainer.resolve(:unique_instance2).call(parms)
265
336
 
266
337
  same_instance = SknContainer.resolve(:the_instance)
338
+
339
+ some_proc = SknContainer.resolve(:some_proc).call
340
+
341
+ * Testing Support:
342
+ - #substitute(...) allows you to mock an existing entry. #substitute is an alias for #register_mock
343
+ - SknContainer.substitute(:the_instance, MyClass.new)
344
+ - #restore! clears all mocked entries. #restore! is an alias for #unregister_mock!
345
+ - SknContainer.restore!
346
+
347
+
348
+ ## Public Methods: SknUtils::ConcurrentJobs classes
349
+ `ConcurrentJobs` behaves as a concurrent thread pool by using Concurrent::Promise from the `concurrent-ruby` gem.
350
+ Enables the definition of Procs, or any callable class, which will be executed in parrallel with the available jobs
351
+ loaded into ConcurrentJobs. Meant to reduce user-sensitive response times when multiple APIs must be invoked.
352
+ Also review the RSpecs for additional useage info.
353
+
354
+ SknUtils::ConcurrentJobs
355
+ #call(async: true) - Instantiate ConcurrentJobs with Async Workers, false for Sync Workers
356
+ #register_jobs(cmds, callable) - Array of Command to be executed by single callable
357
+ #register_job(&block) - Adds callable block to internal worker queue
358
+ #render_jobs - Collect results from all jobs into a Result object
359
+ #elapsed_time_string - "0.012 seconds" string showing duration of last #render_jobs call
360
+
361
+ SknUtils::Result - Contains individual results from each job executed
362
+ #success? - Determines if any job failed
363
+ #messages - Retrieves messages from job results, assumed present when job fails
364
+ #values - Returns an array of individual results from job executions
365
+
366
+ Commands and HttpProcessors are included to demonstrate Job creating patterns. ConcurrentJobs is not restricted
367
+ to Http calls or the command to command handler pattern. Using the #register_job method you can pass callable BLOCK
368
+ and it will be executed when #render_jobs is invoked. HttpProcessor is what I needed and triggered me to add this feature.
369
+
370
+ Example here:
371
+
372
+ ```ruby
373
+ begin
374
+ # CommandJSONPost, CommandFORMGet, CommandJSONGet,
375
+ # CommandJSONPut, CommandFORMDelete
376
+ commands = [
377
+ SknUtils::CommandJSONGet.call(full_url: "http://jsonplaceholder.typicode.com/posts"),
378
+ SknUtils::CommandJSONGet.call(full_url: "https://jsonplaceholder.typicode.com/comments"),
379
+ SknUtils::CommandJSONGet.call(full_url: "https://jsonplaceholder.typicode.com/todos/1"),
380
+ SknUtils::CommandJSONGet.call(full_url: "http://jsonplaceholder.typicode.com/users")
381
+ ]
382
+
383
+ # Initialize the queue with Async Workers by default
384
+ provider = SknUtils::ConcurrentJobs.call
385
+
386
+ # Populate WorkQueue
387
+ provider.register_jobs(commands, SknUtils::HttpProcessor) # mis-spelling these params result in an immediate exception (line 43 below)
388
+
389
+ # Execute WorkQueue
390
+ result = provider.render_jobs
391
+
392
+ if result.success?
393
+ puts "Success: true"
394
+ puts "Values: #{result.values}"
395
+ puts "Messages: #{result.messages}"
396
+ else
397
+ puts "Success: false - errors: #{result.messages.join(', ')}"
398
+ puts "Values: #{result.values}"
399
+ end
267
400
 
401
+ # result.values
402
+ rescue => e
403
+ $stderr.puts e.message, e.backtrace
404
+ end
268
405
 
406
+ ```
407
+
408
+
409
+ ## Public Methods: SknSettings class
410
+ SknSettings is a global constant containing an initialized Object of SknUtils::Configuration using defaults.
411
+ To change the 'development'.yml default please use the following method early or in the case of Rails in 'application.rb
269
412
 
270
- ## Public Methods: SknSettings ONLY
271
- SknSettings is global constant containing an initialized Object of SknUtils::Configuration using defaults
272
- To change the 'development'.yml default please use the following method early or in the case of Rails in 'application.rb
273
413
  #load_config_basename!(config_name) -- Where config_name is the name of yml files stored in the `./config/settings` directory
274
414
  #config_path!(path) -- Where path format is './<dirs>/', default is: './config/'
275
415
  and contains a settings.yml file and a 'path/settings/' directory
@@ -302,9 +442,15 @@ There are many more use cases for Ruby's Hash that this gem just makes easier to
302
442
  #prepend_source!(file_path_or_hash) -- self, adds yaml_file or hash to start of filelist (:reload! required)
303
443
  -------------------------------------------------
304
444
 
445
+ Usage
446
+ -------------------------------------------------
447
+ Dot notation of yaml file contents
448
+ SknSettings.version # => version's value
449
+ -------------------------------------------------
305
450
 
306
451
  ## Public Methods: SknUtils::NestedResult, SknHash & SknSettings
307
- Each concrete Class supports the following utility methods:
452
+ Each concrete Class supports the following utility methods:
453
+
308
454
  #to_hash -- returns a hash of current key/value pairs, including nested
309
455
  #to_json -- returns a json string of current key/value pairs, including nested
310
456
  #hash_from(:base_key) -- exports the internal hash starting with this base level key
@@ -324,6 +470,7 @@ There are many more use cases for Ruby's Hash that this gem just makes easier to
324
470
 
325
471
 
326
472
  ## NestedResult Basic features include:
473
+
327
474
  ```ruby
328
475
  - provides the hash or dot notation methods of accessing values:
329
476
 
@@ -365,6 +512,7 @@ There are many more use cases for Ruby's Hash that this gem just makes easier to
365
512
 
366
513
  * The NestedResult produces these effects when given a params hash;
367
514
  * Follow VALUES that are Hashes, Arrays of Hashes, and Arrays of Arrays of Hashes
515
+
368
516
  ```ruby
369
517
  drb = SknUtils::NestedResult.new(params) Basic dot notation:
370
518
  ---------------------------------------------------- -----------------------------------------------------------------
@@ -389,6 +537,7 @@ There are many more use cases for Ruby's Hash that this gem just makes easier to
389
537
  ```
390
538
 
391
539
  * Expected usage
540
+
392
541
  ```ruby
393
542
  result = SknUtils::NestedResult.new({
394
543
  success: true,
@@ -404,6 +553,7 @@ There are many more use cases for Ruby's Hash that this gem just makes easier to
404
553
 
405
554
 
406
555
  * Wrap additional methods around the core NestedResult feature set
556
+
407
557
  ```ruby
408
558
  class MyPackage < SknUtils::NestedResult
409
559
  def initialize(params={})
@@ -420,10 +570,11 @@ There are many more use cases for Ruby's Hash that this gem just makes easier to
420
570
  ## Installation
421
571
 
422
572
  runtime prereqs:
423
- * V4+ None
424
- * V3+ None
425
- * V2+ None
426
- * V1+ gem 'active_model', '~> 3.0'
573
+ * V5+ None
574
+ * V4+ None
575
+ * V3+ None
576
+ * V2+ None
577
+ * V1+ gem 'active_model', '~> 3.0'
427
578
 
428
579
 
429
580
  Add this line to your application's Gemfile:
@@ -1,9 +1,10 @@
1
1
  title: SknUtils
2
2
  email: skoona@gmail.com
3
3
  description: > # this means to ignore newlines until "baseurl:"
4
- Ruby GEM containing utilitarian classes to help build Ruby applications. SknUtils::NestedResult is the primary class. It is
5
- a threadsafe wrapper over Ruby's Hash with dot.notation, ?.presence, and nested deep-merge features added. I use it for application
6
- settings via YAML files, and as a container for persistent objects.
4
+ Collection of pure-ruby utility classes and modules, with limited
5
+ dependencies, to augment the development of Ruby applications. Value containers supporting nested dot.notation access
6
+ over hashes, and utilities offering dependency injection/lookup, and language extensions support running in a non-rails
7
+ environment. Plus, examples of null objects, class customization, and concurrent processing.
7
8
  baseurl: ""
8
9
  url: https://skoona.github.io/SknServices
9
10
 
@@ -21,4 +22,3 @@ github:
21
22
  author:
22
23
  name: "James Scott, Jr. (a.k.a Skoona)"
23
24
  url: https://keybase.io/skoona
24
-
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # file: concurrent_test_block
4
+ #
5
+
6
+ require 'bundler/setup'
7
+ require 'skn_utils'
8
+
9
+
10
+ # ##
11
+ # MainLine
12
+ # ##
13
+ #
14
+ begin
15
+ # CommandJSONPost, CommandFORMGet, CommandJSONGet,
16
+ # CommandJSONPut, CommandFORMDelete
17
+ commands = [
18
+ SknUtils::CommandJSONGet.call(full_url: "http://jsonplaceholder.typicode.com/posts"),
19
+ SknUtils::CommandJSONGet.call(full_url: "https://jsonplaceholder.typicode.com/comments"),
20
+ SknUtils::CommandJSONGet.call(full_url: "https://jsonplaceholder.typicode.com/todos/1"),
21
+ SknUtils::CommandJSONGet.call(full_url: "http://jsonplaceholder.typicode.com/users")
22
+ ]
23
+
24
+ # Initialize the queue with Async Workers by default
25
+ provider = SknUtils::ConcurrentJobs.call
26
+
27
+ # Populate WorkQueue
28
+ commands.each do |command|
29
+ provider.register_job do
30
+ begin
31
+ SknUtils::HttpProcessor.call(command) # mis-spelling these params result in [SknFailure, SknFailure, ...] results
32
+ rescue => ex
33
+ $stderr.puts ex
34
+ SknFailure.(ex.class.name, "#{ex.message}; #{ex.backtrace[0]}")
35
+ end
36
+ end
37
+ end
38
+
39
+ # Execute WorkQueue
40
+ result = provider.render_jobs
41
+
42
+ if result.success?
43
+ puts "Success: true"
44
+ puts "Values: #{result.values}"
45
+ puts "Messages: #{result.messages}"
46
+ else
47
+ puts "Success: false - errors: #{result.messages.join(', ')}"
48
+ puts "Values: #{result.values}"
49
+ end
50
+
51
+ # result.values
52
+ rescue => e
53
+ $stderr.puts e.message, e.backtrace
54
+ end