skn_utils 5.7.0 → 5.8.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: '01339ef95f65037a1a9951185b69a8ee2fb9160c'
4
- data.tar.gz: fd2bd2b6b3ae66f17b268f6f23abd2d1a8c0e69b
2
+ SHA256:
3
+ metadata.gz: bdbe2b2318e4841c25afdec1e118cc19ff445f8a8b1e08d116715f5b9df0f56e
4
+ data.tar.gz: d42c5e55def5f8c2789714d1fada2f341f59665ba633192732b9e6b48816e253
5
5
  SHA512:
6
- metadata.gz: cb6089054a1e97e7e21d03df41c6622e253487fee45e9799217c8cff211dcb8ca63c39776e15c89876edd88e22a9a22c099a133328bb5786801a0d53ce682924
7
- data.tar.gz: 288b6c71971afd3f0b84b5524d0c96ceec28b7db93a8183ea6c9e31e0a00a974b0eb11f8acbcda03f7b3d0b5160de6e244ec78b7fca13d43f75a63951765e72c
6
+ metadata.gz: b48e34a868729ed2fe63cc77c456a9b9eef99540355d4de6135c7cd5fe96c88b78519cc8384f2eb13c0a29b9652b4e84fbc1624a4674df0ec73c4f95d3762392
7
+ data.tar.gz: c435de19604f41834446ca04084ffc7a559267786974130edc03ad2a540f07eb08111571b13995f67e6bcfc122b215a3d5bb5cf26a905d1e3e85b31e4f0dfad3
data/README.md CHANGED
@@ -75,7 +75,7 @@ use-cases.
75
75
 
76
76
 
77
77
  ## History
78
- 2/3/2030 V5.7.0
78
+ 2/3/2020 V5.7.0
79
79
  Added
80
80
  * RSpec XML_Matchers to spec/support folders
81
81
  * Update ConcurrentJobs JobCommands to support HTTP Headers
@@ -201,39 +201,31 @@ Ruby's Hash object is already extremely flexible, even more so with the addition
201
201
  - enables `SknSettings.root`
202
202
  - `env: !ruby/string:SknUtils::EnvStringHandler <%= ENV.fetch('RACK_ENV', 'development') %>`
203
203
  - enables `SknSettings.env.production?` ...
204
- 1. Since SknSettings is by necessity a global constant, it can serve as Session Storage to keep system objects; like a ROM-RB instance.
205
- 1. In-Memory Key-Store, use it to cache active user objects, or active Integration passwords, and/or objects that are not serializable.
206
- 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)
207
- ```ruby
208
- SknSettings.command_handler = {
209
- Commands::RetrieveAvailableResources => method(:resources_metadata_service),
210
- Commands::RetrieveResourceContent => method(:resource_content_service)
211
- }
212
- ...
213
- SknSettings.command_handler[ cmd.class ].call( cmd )
214
- -- or --
215
- SknSettings.command_handler.key?( cmd.class ) &&
216
- cmd.valid? ? SknSettings.command_handler[ cmd.class ].call( cmd ) : command_not_found_action()
217
- ```
204
+
218
205
  There are many more use cases for Ruby's Hash that this gem just makes easier to implement.
219
206
 
220
207
 
221
208
  ## Public Components
222
209
  SknUtils::NestedResult # Primary Key/Value Container with Dot/Hash notiation support.
223
- SknHash # Wrapper for name only, WITHOUT SknUtils namespace, inherits from SknUtils::NestedResult
224
- SknUtils::ResultBean # Wrapper for name only, inherits from SknUtils::NestedResult
225
- SknUtils::PageControls # Wrapper for name only, inherits from SknUtils::NestedResult
226
- 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
227
214
 
228
- 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
229
218
 
230
- 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
231
220
 
232
- 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
233
224
 
234
- SknSuccess # Three attribute value containers for return codes -- #value, #message, #success
225
+ SknSuccess # Three attribute value containers for consistant return codes -- #value, #message, #success
235
226
  - Extra #payload method returns value as NestResult if value is_a Hash
236
227
  SknFailure # Three attribute value containers for return codes -- #value, #message, #success
228
+
237
229
  SknUtils::ConcurrentJobs # Async/Sync Job executor pool with HTTP support
238
230
  SknUtils::CommandJSONGet # HTTP Get Command class expecting `json` return, located inside `job_commands`
239
231
  SknUtils::CommandJSONPut # HTTP Put Command class expecting `json` return, located inside `job_commands`
@@ -245,7 +237,9 @@ There are many more use cases for Ruby's Hash that this gem just makes easier to
245
237
 
246
238
 
247
239
  ## Public Methods: SknUtils::Configurable module
248
- 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
+
249
243
  ```ruby
250
244
  # (1) First establish the method names of class values desired.
251
245
  ################
@@ -310,21 +304,27 @@ There are many more use cases for Ruby's Hash that this gem just makes easier to
310
304
  ```
311
305
 
312
306
 
313
- ## Public Methods: SknRegistry ONLY
314
- `SknContainer` is global constant assigned to an instantiated instance of `SknRegistry`.
315
- Returns the keyed value as the original instance/value or if provided a proc the result of calling that proc.
316
- 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.
317
315
 
318
316
  #register(key, contents = nil, options = {})
319
317
  - example:
320
318
  SknContainer.register(:some_klass, MyClass) -- class as value
321
319
  SknContainer.register(:the_instance, MyClass.new) -- Object Instance as value
322
- 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
323
323
 
324
324
  SknContainer -- #register returns self to enable chaining
325
325
  .register(:unique_instance, -> {MyClass.new})
326
- .register(:the_instance, MyClass.new)
327
- .register(:some_klass, MyClass)
326
+ .register(:the_instance, MyClass.new)
327
+ .register(:some_klass, MyClass)
328
328
 
329
329
  #resolve(key)
330
330
  - example:
@@ -332,20 +332,24 @@ There are many more use cases for Ruby's Hash that this gem just makes easier to
332
332
  instance = SknContainer.resolve(:some_klass).new
333
333
 
334
334
  obj_instance1 = SknContainer.resolve(:unique_instance)
335
- obj_instance2 = SknContainer.resolve(:unique_instance)
335
+ obj_instance2 = SknContainer.resolve(:unique_instance2).call(parms)
336
336
 
337
337
  same_instance = SknContainer.resolve(:the_instance)
338
+
339
+ some_proc = SknContainer.resolve(:some_proc).call
338
340
 
339
341
  * Testing Support:
340
- - #substitute(...) allows you to mock an existing entry. #substitute is an alias for #register_mock
342
+ - #substitute(...) allows you to mock an existing entry. #substitute is an alias for #register_mock
343
+ - SknContainer.substitute(:the_instance, MyClass.new)
341
344
  - #restore! clears all mocked entries. #restore! is an alias for #unregister_mock!
345
+ - SknContainer.restore!
342
346
 
343
347
 
344
- ## Public Methods: SknUtils::ConcurrentJobs ONLY
345
- `ConcurrentJobs` behaves as a concurrent thread pool by using Concurrent::Promise from the `concurrent-ruby` gem.
346
- Enables the definition of Procs, or any callable class, which will be executed in parrallel the available jobs
347
- loaded into ConcurrentJobs. Meant to reduce user-sensitive response times when multiple APIs must be invoked.
348
- Also review the RSpecs for additional useage info.
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.
349
353
 
350
354
  SknUtils::ConcurrentJobs
351
355
  #call(async: true) - Instantiate ConcurrentJobs with Async Workers, false for Sync Workers
@@ -359,11 +363,12 @@ There are many more use cases for Ruby's Hash that this gem just makes easier to
359
363
  #messages - Retrieves messages from job results, assumed present when job fails
360
364
  #values - Returns an array of individual results from job executions
361
365
 
362
- Commands and HttpProcessors are included to demonstrate Job creating patterns. ConcurrentJobs is not restricted
363
- to Http calls or the command to command handler pattern. Using the #register_job method you can pass callable BLOCK
364
- and it will be executed when #render_jobs is invoked. HttpProcessor is what I needed and triggered me to add this feature.
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:
365
371
 
366
- Example here:
367
372
  ```ruby
368
373
  begin
369
374
  # CommandJSONPost, CommandFORMGet, CommandJSONGet,
@@ -401,10 +406,10 @@ end
401
406
  ```
402
407
 
403
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
404
412
 
405
- ## Public Methods: SknSettings ONLY
406
- SknSettings is a global constant containing an initialized Object of SknUtils::Configuration using defaults
407
- To change the 'development'.yml default please use the following method early or in the case of Rails in 'application.rb
408
413
  #load_config_basename!(config_name) -- Where config_name is the name of yml files stored in the `./config/settings` directory
409
414
  #config_path!(path) -- Where path format is './<dirs>/', default is: './config/'
410
415
  and contains a settings.yml file and a 'path/settings/' directory
@@ -437,9 +442,15 @@ end
437
442
  #prepend_source!(file_path_or_hash) -- self, adds yaml_file or hash to start of filelist (:reload! required)
438
443
  -------------------------------------------------
439
444
 
445
+ Usage
446
+ -------------------------------------------------
447
+ Dot notation of yaml file contents
448
+ SknSettings.version # => version's value
449
+ -------------------------------------------------
440
450
 
441
451
  ## Public Methods: SknUtils::NestedResult, SknHash & SknSettings
442
- Each concrete Class supports the following utility methods:
452
+ Each concrete Class supports the following utility methods:
453
+
443
454
  #to_hash -- returns a hash of current key/value pairs, including nested
444
455
  #to_json -- returns a json string of current key/value pairs, including nested
445
456
  #hash_from(:base_key) -- exports the internal hash starting with this base level key
@@ -459,6 +470,7 @@ end
459
470
 
460
471
 
461
472
  ## NestedResult Basic features include:
473
+
462
474
  ```ruby
463
475
  - provides the hash or dot notation methods of accessing values:
464
476
 
@@ -500,6 +512,7 @@ end
500
512
 
501
513
  * The NestedResult produces these effects when given a params hash;
502
514
  * Follow VALUES that are Hashes, Arrays of Hashes, and Arrays of Arrays of Hashes
515
+
503
516
  ```ruby
504
517
  drb = SknUtils::NestedResult.new(params) Basic dot notation:
505
518
  ---------------------------------------------------- -----------------------------------------------------------------
@@ -524,6 +537,7 @@ end
524
537
  ```
525
538
 
526
539
  * Expected usage
540
+
527
541
  ```ruby
528
542
  result = SknUtils::NestedResult.new({
529
543
  success: true,
@@ -539,6 +553,7 @@ end
539
553
 
540
554
 
541
555
  * Wrap additional methods around the core NestedResult feature set
556
+
542
557
  ```ruby
543
558
  class MyPackage < SknUtils::NestedResult
544
559
  def initialize(params={})
@@ -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
-
@@ -16,7 +16,8 @@ module SknUtils
16
16
  def call
17
17
  @blk.call
18
18
  rescue => ex
19
- SknFailure.(ex.class.name, { cause: ex.message, backtrace: ex.backtrace[0..8]})
19
+ failures = ex.backtrace.map {|x| x.split("/").last }.join(",")
20
+ SknFailure.(ex.class.name, { cause: ex.message, backtrace: failures})
20
21
  end
21
22
  end
22
23
 
@@ -28,7 +29,8 @@ module SknUtils
28
29
  def call
29
30
  @blk.value
30
31
  rescue => ex
31
- SknFailure.(ex.class.name, { cause: ex.message, backtrace: ex.backtrace[0..8]})
32
+ failures = ex.backtrace.map {|x| x.split("/").last }.join(",")
33
+ SknFailure.(ex.class.name, { cause: ex.message, backtrace: failures})
32
34
  end
33
35
  end
34
36
 
@@ -50,11 +52,20 @@ module SknUtils
50
52
  end
51
53
  end
52
54
 
55
+ class CallableWrapperJob
56
+ def self.call(callable, command)
57
+ callable.call(command)
58
+ rescue => ex
59
+ failures = ex.backtrace.map {|x| x.split("/").last }.join(",")
60
+ SknFailure.(ex.class.name, { cause: ex.message, backtrace: failures})
61
+ end
62
+ end
53
63
  class JobWrapper
54
64
  def self.call(command, callable)
55
65
  callable.call(command)
56
66
  rescue => ex
57
- SknFailure.(ex.class.name, { cause: ex.message, backtrace: ex.backtrace[0..8]})
67
+ failures = ex.backtrace.map {|x| x.split("/").last }.join(",")
68
+ SknFailure.(ex.class.name, { cause: ex.message, backtrace: failures})
58
69
  end
59
70
  end
60
71
 
@@ -93,7 +104,8 @@ module SknUtils
93
104
  res = worker.call
94
105
  acc.push( res.nil? ? SknFailure.("Unknown", {cause: "Nil Return Value to render Jobs", backtrace: []}) : res )
95
106
  rescue => ex
96
- acc.push SknFailure.(ex.class.name, { cause: ex.message, backtrace: ex.backtrace[0..8]})
107
+ failures = ex.backtrace.map {|x| x.split("/").last }.join(",")
108
+ acc.push SknFailure.(ex.class.name, { cause: ex.message, backtrace: failures})
97
109
  end
98
110
  end
99
111
  @elapsed_time_string = SknUtils.duration(stime)
@@ -63,6 +63,7 @@ module SknUtils
63
63
  # - metadata = platform metadata container
64
64
  # - userdata = user area
65
65
  # - metrics = platform metrics container
66
+ # - ...
66
67
  # #with(*user_attrs, enable_root: true|false) - defaults to enable of Main Class Attrs
67
68
  # ##
68
69
  # User-Defined Attrs
@@ -3,6 +3,47 @@
3
3
  # Ref: https://yukimotopress.github.io/http
4
4
 
5
5
  module SknUtils
6
+ # #################################################
7
+ #
8
+ class CommandJSONPDelete
9
+ def self.call(options) # {full_url:,username:,userpass:,payload:,headers:}
10
+ new(options)
11
+ end
12
+
13
+ def json?
14
+ true
15
+ end
16
+
17
+ def uri
18
+ @_uri
19
+ end
20
+
21
+ def request
22
+ req = @_headers.nil? ? Net::HTTP::Delete.new(uri.request_uri) : Net::HTTP::Delete.new(uri.request_uri, @_headers) # Generate HTTPRequest object
23
+ req.basic_auth(@_username, @_userpass) if credentials?
24
+ req.content_type = 'application/json'
25
+ req.body = formatted_data
26
+ req
27
+ end
28
+
29
+ private
30
+
31
+ def initialize(opts={})
32
+ @_username = opts[:username]
33
+ @_userpass = opts[:userpass]
34
+ @_headers = opts[:headers]
35
+ @_uri = URI.parse( opts[:full_url])
36
+ @_data = opts[:payload]
37
+ end
38
+
39
+ def formatted_data
40
+ @_data.respond_to?(:to_json) ? @_data.to_json : @_data
41
+ end
42
+
43
+ def credentials?
44
+ !(@_username.nil? || @_userpass.nil?)
45
+ end
46
+ end
6
47
 
7
48
  # #################################################
8
49
  #
@@ -4,7 +4,7 @@
4
4
  module SknUtils
5
5
  class Version
6
6
  MAJOR = 5
7
- MINOR = 7
7
+ MINOR = 8
8
8
  PATCH = 0
9
9
 
10
10
  def self.to_s
@@ -1,48 +1,49 @@
1
+ # frozen_string_literal: true
1
2
  # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
3
- # lib = File.expand_path('../lib', __dir__)
4
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
- require 'skn_utils/version'
3
+
4
+ require_relative 'lib/skn_utils/version'
6
5
 
7
6
  Gem::Specification.new do |spec|
8
7
  spec.name = 'skn_utils'
9
8
  spec.version = SknUtils::VERSION
10
9
  spec.author = 'James Scott Jr'
11
10
  spec.email = 'skoona@gmail.com'
12
- spec.summary = <<-EOF
13
- SknUtils contains a small collection of Ruby utilities, the first being a NestedResult a key/value container.
14
- EOF
15
-
16
- spec.description = <<-EOF
17
- The intent of the NestedResult class is to be a container for data values composed of key/value pairs,
18
- with easy access to its contents, and on-demand transformation back to the hash (#to_hash).
11
+ spec.summary = <<-DESC
12
+ Ruby utilities for dependency injection/lookup, class customizations, and dot.notion access over nested hashes.
13
+ DESC
14
+ spec.description = <<-DESC
15
+ Value containers supporting nested dot.notation access over hashes, and utilities offering dependency injection/lookup, and
16
+ language extensions support running in a non-rails environment. Plus, examples of null objects, class customization,
17
+ and concurrent processing.
19
18
 
20
19
  Review the RSpec tests, and or review the README for more details.
21
- EOF
22
- spec.post_install_message = <<-EOF
20
+ DESC
21
+
22
+ spec.post_install_message = <<-DESC
23
23
  This version includes modified versions of SknUtils::ResultBean, SknUtils::PageControls classes, which inherit from
24
24
  SknUtils::NestedResult class. SknUtils::NestedResult replaces those original classes and consolidates their function.
25
- EOF
25
+ DESC
26
+
26
27
  spec.homepage = "https://github.com/skoona/skn_utils"
27
28
  spec.license = "MIT"
28
29
  spec.platform = Gem::Platform::RUBY
29
- spec.files = `git ls-files -z`.split("\x0")
30
+ spec.files = `git ls-files -z`.split("\x0")
30
31
  spec.executables = []
31
- spec.test_files = spec.files.grep(%r{^(spec)/})
32
- spec.require_paths = ['lib']
32
+ spec.test_files = spec.files.grep(%r{^(spec)/})
33
+ spec.require_paths = %w[lib]
34
+ spec.extra_rdoc_files = Dir["README.md", "CODE_OF_CONDUCT.md", "LICENSE"]
33
35
 
34
36
  spec.add_runtime_dependency 'deep_merge', '~> 1'
35
37
  spec.add_runtime_dependency 'concurrent-ruby', '~> 1'
36
38
  spec.add_runtime_dependency 'thor', '~> 0'
37
39
 
38
- spec.add_development_dependency "bundler", "~> 1"
39
- spec.add_development_dependency "rake", "~> 10"
40
- spec.add_development_dependency "rspec", '~> 3'
41
- spec.add_development_dependency "pry", "~> 0"
40
+ spec.add_development_dependency "bundler", ">= 1"
41
+ spec.add_development_dependency "rake", ">= 12.3.3"
42
+ spec.add_development_dependency "rspec", '>= 3'
43
+ spec.add_development_dependency "pry", ">= 0"
42
44
  spec.add_development_dependency "pry-coolline"
43
- spec.add_development_dependency "simplecov", "~> 0"
44
- spec.add_development_dependency 'benchmark-ips', '~> 2'
45
+ spec.add_development_dependency "simplecov", ">= 0"
46
+ spec.add_development_dependency 'benchmark-ips', '>= 2'
45
47
  spec.add_development_dependency 'webmock'
46
48
 
47
-
48
49
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: skn_utils
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.7.0
4
+ version: 5.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Scott Jr
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-02-03 00:00:00.000000000 Z
11
+ date: 2020-05-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: deep_merge
@@ -56,56 +56,56 @@ dependencies:
56
56
  name: bundler
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
61
  version: '1'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '1'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rake
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - "~>"
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
- version: '10'
75
+ version: 12.3.3
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - "~>"
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
- version: '10'
82
+ version: 12.3.3
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rspec
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - "~>"
87
+ - - ">="
88
88
  - !ruby/object:Gem::Version
89
89
  version: '3'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - "~>"
94
+ - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '3'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: pry
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - "~>"
101
+ - - ">="
102
102
  - !ruby/object:Gem::Version
103
103
  version: '0'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - "~>"
108
+ - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  - !ruby/object:Gem::Dependency
@@ -126,28 +126,28 @@ dependencies:
126
126
  name: simplecov
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - "~>"
129
+ - - ">="
130
130
  - !ruby/object:Gem::Version
131
131
  version: '0'
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
- - - "~>"
136
+ - - ">="
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: benchmark-ips
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
- - - "~>"
143
+ - - ">="
144
144
  - !ruby/object:Gem::Version
145
145
  version: '2'
146
146
  type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
- - - "~>"
150
+ - - ">="
151
151
  - !ruby/object:Gem::Version
152
152
  version: '2'
153
153
  - !ruby/object:Gem::Dependency
@@ -164,14 +164,18 @@ dependencies:
164
164
  - - ">="
165
165
  - !ruby/object:Gem::Version
166
166
  version: '0'
167
- description: "The intent of the NestedResult class is to be a container for data values
168
- composed of key/value pairs, \nwith easy access to its contents, and on-demand transformation
169
- back to the hash (#to_hash).\n\nReview the RSpec tests, and or review the README
167
+ description: "Value containers supporting nested dot.notation access over hashes,
168
+ and utilities offering dependency injection/lookup, and \nlanguage extensions support
169
+ running in a non-rails environment. Plus, examples of null objects, class customization,
170
+ \nand concurrent processing.\n\nReview the RSpec tests, and or review the README
170
171
  for more details.\n"
171
172
  email: skoona@gmail.com
172
173
  executables: []
173
174
  extensions: []
174
- extra_rdoc_files: []
175
+ extra_rdoc_files:
176
+ - README.md
177
+ - CODE_OF_CONDUCT.md
178
+ - LICENSE
175
179
  files:
176
180
  - ".gitignore"
177
181
  - ".rspec"
@@ -180,7 +184,6 @@ files:
180
184
  - Gemfile
181
185
  - LICENSE
182
186
  - README.md
183
- - README.rdoc
184
187
  - Rakefile
185
188
  - _config.yml
186
189
  - bin/bench_nested_result.rb
@@ -266,11 +269,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
266
269
  version: '0'
267
270
  requirements: []
268
271
  rubyforge_project:
269
- rubygems_version: 2.6.14
272
+ rubygems_version: 2.7.9
270
273
  signing_key:
271
274
  specification_version: 4
272
- summary: SknUtils contains a small collection of Ruby utilities, the first being a
273
- NestedResult a key/value container.
275
+ summary: Ruby utilities for dependency injection/lookup, class customizations, and
276
+ dot.notion access over nested hashes.
274
277
  test_files:
275
278
  - spec/factories/environments/development.yml
276
279
  - spec/factories/environments/production.yml
@@ -1,379 +0,0 @@
1
- [![Gem Version](https://badge.fury.io/rb/skn_utils.svg)](http://badge.fury.io/rb/skn_utils)
2
-
3
- = SknUtils
4
- ==== SknUtils::NestedResult class; dynamic key/value container
5
- The intent of this gem is to be a container of data results or key/value pairs, with easy access to its contents, and on-demand transformation back to the hash (#to_hash).
6
-
7
- Ruby Gem containing a Ruby PORO (Plain Old Ruby Object) that can be instantiated at runtime with an input hash. This library creates
8
- an Object with Dot or Hash notational accessors to each key's value. Additional key/value pairs can be added post-create
9
- by 'obj.my_new_var = "some value"', or simply assigning it.
10
-
11
- * Transforms the initialization hash into accessable object instance values, with their keys as method names.
12
- * If the key's value is also a hash, it too will become an Object.
13
- * if the key's value is a Array of Hashes, or Array of Arrays of Hashes, each element of the Arrays will become an Object.
14
- * The current key/value (including nested) pairs are returned via #to_hash or #to_json when and if needed.
15
-
16
-
17
- == New Features
18
- 03/2017 V3.0.0
19
- Added SknUtils::NestedResult to replace, or be an alternate, to ResultBean, GenericBean, PageControls, ValueBean, and AttributeHelper.
20
- NestedResult overcome issues with serialization via Marshal and Yaml/Psych.
21
- NestedResult will properly encode all hash based key/value pairs of input and decodes it via #to_h or #to_json
22
- NestedResult encodes everything given no matter how deeply its nested, unlike the prior version where you had control over nesting.
23
-
24
- 10/2016 V2.0.6
25
- Added an SknUtils::NullObject and SknUtils::nullable?(value) extracted from [Avdi Grimm's Confident Code](https://gist.github.com/jschoolcraft/979827)
26
- The NullObject class has great all around utility, check out it's specs!
27
-
28
- 08/2016 V2.0.3
29
- Added an exploritory ActionService class and RSpec test, triggered by reading [Kamil Lelonek](https://blog.lelonek.me/what-service-objects-are-not-7abef8aa2f99#.p64vudxq4)
30
- I don't support his approach, but the CreateTask class caught my attention as a Rubyist.
31
-
32
- 12/2015 V2.0
33
- All references to ActiveRecord or Rails has been removed to allow use in non-Rails environments
34
- as a result serialization is done with standard Ruby Hash serialization methods; by first transforming
35
- object back to a hash using its #to_hash method.
36
-
37
- 06/2015 V1.5.1 commit #67ef656
38
- Last Version to depend on Rails (ActiveModel) for #to_json and #to_xml serialization
39
-
40
-
41
- == Configuration Options
42
- None required other than initialization hash
43
-
44
-
45
- == Public Methods
46
- Each concrete Class supports the following utility methods:
47
- #to_hash -- returns a hash of current key/value pairs, including nested
48
- #to_json -- returns a json string of current key/value pairs, including nested
49
- #hash_from(:base_key) -- exports the internal hash starting with this base level key
50
- #obj.obj2.hash_from(:base) -- exports the internal hash starting from this nested base level key
51
- #[] -- returns value of attr, when #[<attr_name_symbol>]
52
- #[]=(attr, value) -- assigns value to existing attr, or creates a new key/value pair
53
- #<attr>? -- detects true/false presence? of attr, and non-blank existance of attr's value; when #address?
54
- #<attr> -- returns value of named attribute
55
- #<attr> = (value) -- assigns value to existing attr, or creates a new key/value pair
56
- -- Where <attr> is a key value from the initial hash, or a key that was/will be dynamically added
57
-
58
-
59
-
60
- == Public Components
61
- SknUtils::NestedResult # >= V 3.0.0 Primary Key/Value Container with Dot/Hash notiation support.
62
-
63
-
64
- *** <= V 2.0.6 Depreciated, will be removed in next release ***
65
-
66
- Inherit from NestedResultBase or instantiate an pre-built Class:
67
- SknUtils::ResultBean # => Not Serializable and follows hash values only.
68
- SknUtils::PageControls # => Serializable and follows hash values and arrays of hashes.
69
- SknUtils::GenericBean # => Serializable and follows hash values only.
70
- SknUtils::ValueBean # => Serializable and DOES NOT follows hash values.
71
- or Include SknUtils::AttributeHelpers # => Adds getter/setters, and hash notation access to instance vars of any object.
72
-
73
-
74
- == Basic features include:
75
- ```ruby
76
- - provides the hash or dot notation methods of accessing values:
77
-
78
- $ obj = SknUtils::NestedResult.new({value1: "some value", value2: {one: 1, two: "two"}})
79
- $ x = obj.value1
80
- $ x = obj.value2.one
81
- $ x = obj["value1"]
82
- $ x = obj[:value1]
83
-
84
- - enables serialization:
85
- Internally supports #to_hash and #to_json
86
-
87
- $ person = SknUtils::NestedResult.new({name: "Bob"})
88
- $ person.to_hash # => {"name"=>"Bob"}
89
- $ person.to_json # => "{\"name\":\"Bob\"}"
90
- $ dmp = Marshal.dump(person) # => "\x04\bo:\x1ASknUtils::NestedResult\x06:\n@nameI\"\bBob\x06:\x06ET"
91
- $ person2 = Marshal.load(dmp) # => #<SknUtils::NestedResult:0x007faede906d40 @name="Bob">
92
-
93
- - post create additions:
94
-
95
- 'obj = SknUtils::NestedResult.new({value1: "some value", value2: {one: 1, two: "two"}})
96
- 'x = obj.one' --causes NoMethodError
97
- 'x = obj.one = 'some other value' --creates a new instance value with accessors
98
- 'x = obj.one = {key1: 1, two: "two"}' --creates a new ***bean as the value of obj.one
99
- 'y = obj.one.two' --returns "two"
100
- 'y = obj.one[:two] --returns "two"
101
- 'y = obj.one['two'] --returns "two"
102
-
103
- - supports predicates <attr>? method patterns: target must exist and have a non-empty/valid value
104
-
105
- $ obj = SknUtils::NestedResult.new({name: "Something", active: false, phone: "2609998888"})'
106
- $ obj.name?' # => true -- true or false, like obj.name.present?
107
- $ obj.active? # => true -- your asking if method exist with a valid value, not what the value is!
108
- $ obj.street? # => false
109
- ```
110
-
111
-
112
- == Usage:
113
-
114
- * The NestedResult produces these effects when given a params hash;
115
- * Follow VALUES that are Hashes, Arrays of Hashes, and Arrays of Arrays of Hashes
116
- ```ruby
117
- drb = SknUtils::NestedResult.new(params) Basic dot notation:
118
- ---------------------------------------------------- -----------------------------------------------------------------
119
-
120
- * params = {one: 1, drb.one = 1
121
- two: { one: 1, two: "two"}, drb.two = <SknUtils::NestedResult>
122
- drb.two.two = 'two'
123
-
124
- three: [ {one: 'one', two: 2}, drb.three.first.one = 'one'
125
- {three: 'three', four: 4} drb.three[1].four = 4
126
- ], drb.three.last.three = 'three'
127
-
128
- four: [
129
- [ {one: 'one', two: 2}, drb.four.first.first.one = 'one'
130
- {three: 'three', four: 4} ], drb.four.first.last.four = 4
131
- [ { 5: 'five', 6: 'six'}, drb.four[1][0][5] = 'five' # number keys require hash notation :[]
132
- {five: '5', six: 6} ] drb.four[1].last.six = 6
133
- ],
134
- 'five' => [1, 2, 3] drb.five = [1, 2, 3]
135
- 6 => 'number key' drb[6] = 'number key'
136
- }
137
- ```
138
-
139
- * Expected usage
140
- ```ruby
141
- result = SknUtils::NestedResult.new({
142
- success: true,
143
- message: "",
144
- payload: {package: 'of key/value pairs from operations'}
145
- })
146
- ...
147
-
148
- if result.success && result.payload.package?
149
- # do something with result.payload
150
- end
151
- ```
152
-
153
-
154
- * Wrap additional methods around the core NestedResult feature set
155
- ```ruby
156
- class MyPackage < SknUtils::NestedResult
157
- def initialize(params={})
158
- super
159
- end
160
-
161
- def additional_method
162
- # do something
163
- end
164
- end
165
- ```
166
-
167
-
168
- == Installation
169
-
170
- runtime prereqs:
171
- V3+ None
172
- V2+ None
173
- V1+ gem 'active_model', '~> 3.0'
174
-
175
-
176
- Add this line to your application's Gemfile:
177
- ```ruby
178
- gem 'skn_utils'
179
- ```
180
-
181
-
182
- And then execute:
183
- $ bundle
184
-
185
-
186
- Or install it yourself as:
187
- $ gem install skn_utils
188
-
189
-
190
- == Build
191
-
192
- 1. $ git clone git@github.com:skoona/skn_utils.git
193
- 2. $ cd skn_utils
194
- 3. $ gem install bundler
195
- 4. $ bundle install
196
- 5. $ bundle exec rspec
197
- 6. $ gem build skn_utils.gemspec
198
- 7. $ gem install skn_utils
199
- * Done
200
-
201
-
202
- == Console Workout
203
-
204
- Start with building gem first.
205
- ```bash
206
- $ cd skn_utils
207
- $ bin/console
208
-
209
- [1] pry(main)> rb = SknUtils::NestedResult.new({sample: [{one: "one", two: "two"},{one: 1, two: 2}] })
210
- [2] pry(main)> pg = SknUtils::NestedResult.new({sample: [{three: 3, four: 4},{five: 'five', two: 'two'}] })
211
- [3] pry(main)> pg.sample.first.three
212
- [4] pry(main)> rb.sample.first.one
213
- [5] pry(main)> rb.sample.first[:one]
214
- [6] pry(main)> rb.hash_from(:sample)
215
- [7] pry(main)> rb.sample?
216
- [8] pry(main)> rb.sample[0].one?
217
-
218
- [n] pry(main)> exit
219
- * Done
220
- ```
221
-
222
- == Contributing
223
-
224
- 1. Fork it
225
- 2. Create your feature branch (`git checkout -b my-new-feature`)
226
- 3. Commit your changes (`git commit -am 'Add some feature'`)
227
- 4. Push to the branch (`git push origin my-new-feature`)
228
- 5. Create a new Pull Request
229
-
230
-
231
- == License
232
-
233
- The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
234
-
235
- === Notes:
236
- ```ruby
237
- class ApplicationSchema < Dry::Validation::Schema
238
- configure do |config|
239
- option :record
240
- option :machine_repository, Machine
241
- option :user_repository, User
242
- option :temporary_token_repository, TemporaryToken
243
-
244
- config.messages_file = 'config/locales/validations.yml'
245
- end
246
-
247
- ...
248
-
249
- end
250
-
251
- module Sessions
252
- AuthenticateUserSchema = Dry::Validation.Schema(ApplicationSchema) do
253
- required(:email).filled(:str?)
254
- required(:password).filled(:str?)
255
-
256
- validate(exists?: :email) do |email|
257
- user_repository.find_by(email: email).present?
258
- end
259
- end
260
- end
261
- ```
262
-
263
- from: Andy Holland @AMHOL, roda-action
264
- ```ruby
265
- class Roda
266
- ContainerError = Class.new(::Exception)
267
-
268
- module RodaPlugins
269
- # The container plugin allows your application to
270
- # act as a container, you can register values
271
- # with your application (container) and resolve them later.
272
- #
273
- # If you register something that responds to call, the result of
274
- # call will be returned each time you resolve it.
275
- #
276
- # Example:
277
- #
278
- # plugin :container
279
- #
280
- # class UserRepository
281
- # def self.first
282
- # { name: 'Jack' }
283
- # end
284
- # end
285
- #
286
- # MyApplication.register(:user_repository, UserRepository)
287
- # MyApplication.resolve(:user_repository).first
288
- #
289
- # class PersonRepository
290
- # def first
291
- # { name: 'Gill' }
292
- # end
293
- # end
294
- #
295
- # MyApplication.register(:person_repository, -> { PersonRepository.new })
296
- # MyApplication.resolve(:person_repository).first
297
- module Container
298
- class Container < RodaCache
299
- def register(key, contents = nil, options = {}, &block)
300
- if block_given?
301
- item = block
302
- options = contents if contents.is_a?(::Hash)
303
- else
304
- item = contents
305
- end
306
-
307
- self[key] = Content.new(item, options)
308
- end
309
-
310
- def resolve(key)
311
- content = self.fetch(key) do
312
- fail ::Roda::ContainerError, "Nothing registered with the name #{key}"
313
- end
314
-
315
- content.call
316
- end
317
- end
318
-
319
- class Content
320
- attr_reader :item, :options
321
-
322
- def initialize(item, options = {})
323
- @item, @options = item, {
324
- call: item.is_a?(::Proc)
325
- }.merge(options)
326
- end
327
-
328
- def call
329
- if options[:call] == true
330
- item.call
331
- else
332
- item
333
- end
334
- end
335
- end
336
-
337
- module ClassMethods
338
- attr_reader :container
339
- private :container
340
-
341
- def self.extended(subclass)
342
- subclass.instance_variable_set(:@container, Container.new)
343
- super
344
- end
345
-
346
- def inherited(subclass)
347
- subclass.instance_variable_set(:@container, container)
348
- super
349
- end
350
-
351
- def instance
352
- Thread.current[:__container__]
353
- end
354
-
355
- def register(key, contents = nil, options = {}, &block)
356
- container.register(key, contents, options, &block)
357
- end
358
-
359
- def resolve(key)
360
- container.resolve(key)
361
- end
362
-
363
- def detach_container
364
- @container = container.dup
365
- end
366
- end
367
-
368
- module InstanceMethods
369
- def call(*args, &block)
370
- Thread.current[:__container__] = self.class.send(:container).dup
371
- super
372
- end
373
- end
374
- end
375
-
376
- register_plugin(:container, Container)
377
- end
378
- end
379
- ```