skn_utils 5.7.0 → 5.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- 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
- ```