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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # ##
2
4
  # lib/skn_utils/configuration.rb
3
5
  #
@@ -1,7 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # ##
2
4
  # File: ./lib/skn_utils/core_extensions.rb --
3
5
  # -- from: Rails 4.1 ActiveSupport:lib/active_support/core_ext/object/blank.rb
4
6
  # -- Ref: https://6ftdan.com/allyourdev/2015/01/20/refinements-over-monkey-patching/
7
+ # -- Ref: https://medium.com/rubycademy/the-complete-guide-to-create-a-copy-of-an-object-in-ruby-part-ii-cd28a99d58d9
5
8
 
6
9
  module SknUtils
7
10
  module CoreObjectExtensions
@@ -51,6 +54,15 @@ module SknUtils
51
54
  def presence
52
55
  self if present?
53
56
  end
57
+
58
+ def duplicable?
59
+ true
60
+ end
61
+
62
+ def deep_dup
63
+ duplicable? ? dup : self
64
+ end
65
+
54
66
  end
55
67
 
56
68
  class ::NilClass
@@ -94,6 +106,10 @@ module SknUtils
94
106
  #
95
107
  # @return [true, false]
96
108
  alias_method :blank?, :empty?
109
+
110
+ def deep_dup
111
+ map(&:deep_dup)
112
+ end
97
113
  end
98
114
 
99
115
  class ::Hash
@@ -104,6 +120,19 @@ module SknUtils
104
120
  #
105
121
  # @return [true, false]
106
122
  alias_method :blank?, :empty?
123
+
124
+ def deep_dup
125
+ hash = dup
126
+ each_pair do |key, value|
127
+ if key.frozen? && ::String === key
128
+ hash[key] = value.deep_dup
129
+ else
130
+ hash.delete(key)
131
+ hash[key.deep_dup] = value.deep_dup
132
+ end
133
+ end
134
+ hash
135
+ end
107
136
  end
108
137
 
109
138
  class ::String
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module SknUtils
3
4
  class DottedHash < NestedResult
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # File: ./lib/skn_utils/env_string_handler.rb
2
4
  #
3
5
  # Wrapping a string in this class gives you a prettier way to test
@@ -0,0 +1,34 @@
1
+ # ##
2
+ #
3
+ #
4
+ module SknUtils
5
+
6
+ class HttpProcessor
7
+
8
+ def self.call(command)
9
+ completion = false
10
+
11
+ response = Net::HTTP.start( command.uri.host,command.uri.port,
12
+ use_ssl: command.uri.scheme.eql?("https")
13
+ ) do |http|
14
+ http.open_timeout = 5 # in seconds, for internal http timeouts
15
+ http.read_timeout = 15 # in seconds
16
+ if command.uri.scheme.eql?("https")
17
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
18
+ end
19
+ http.request(command.request)
20
+ end
21
+
22
+ if ( response.kind_of?(Net::HTTPClientError) or response.kind_of?(Net::HTTPServerError) )
23
+ completion = SknFailure.call(response.code, response.message)
24
+ else
25
+ payload = command.json? ? JSON.load(response.body) : response.body
26
+ completion = SknSuccess.call(payload, response.class.name)
27
+ end
28
+
29
+ completion
30
+ rescue => exception
31
+ SknFailure.call(command.uri.request_uri, "#{exception.message}; #{exception.backtrace[0]}")
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,247 @@
1
+ # ##
2
+ #
3
+ # Ref: https://yukimotopress.github.io/http
4
+
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
47
+
48
+ # #################################################
49
+ #
50
+ class CommandJSONPost
51
+ def self.call(options) # {full_url:,username:,userpass:,payload:,headers:}
52
+ new(options)
53
+ end
54
+
55
+ def json?
56
+ true
57
+ end
58
+
59
+ def uri
60
+ @_uri
61
+ end
62
+
63
+ def request
64
+ req = @_headers.nil? ? Net::HTTP::Post.new(uri.path) : Net::HTTP::Post.new(uri.path, @_headers) # Generate HTTPRequest object
65
+ req.basic_auth(@_username, @_userpass) if credentials?
66
+ req.content_type = 'application/json'
67
+ req.body = formatted_data
68
+ req
69
+ end
70
+
71
+ private
72
+
73
+ def initialize(opts={})
74
+ @_username = opts[:username]
75
+ @_userpass = opts[:userpass]
76
+ @_headers = opts[:headers]
77
+ @_uri = URI.parse( opts[:full_url])
78
+ @_data = opts[:payload]
79
+ end
80
+
81
+ def formatted_data
82
+ @_data.respond_to?(:to_json) ? @_data.to_json : @_data
83
+ end
84
+
85
+ def credentials?
86
+ !(@_username.nil? || @_userpass.nil?)
87
+ end
88
+ end
89
+
90
+
91
+ # #################################################
92
+ #
93
+ class CommandFORMPost
94
+ def self.call(options) # {full_url:,username:,userpass:,payload:,headers:}
95
+ new(options)
96
+ end
97
+
98
+ def json?
99
+ false
100
+ end
101
+
102
+ def uri
103
+ @_uri
104
+ end
105
+
106
+ def request
107
+ req = @_headers.nil? ? Net::HTTP::Post.new(uri.path) : Net::HTTP::Post.new(uri.path, @_headers) # Generate HTTPRequest object
108
+ req.basic_auth(@_username, @_userpass) if credentials?
109
+ req.content_type = 'application/x-www-form-urlencoded'
110
+ req.set_form_data(formatted_data)
111
+ req
112
+ end
113
+
114
+ private
115
+
116
+ def initialize(opts={})
117
+ @_username = opts[:username]
118
+ @_userpass = opts[:userpass]
119
+ @_headers = opts[:headers]
120
+ @_uri = URI.parse( opts[:full_url])
121
+ @_data = opts[:payload]
122
+ end
123
+
124
+ def formatted_data
125
+ @_data
126
+ end
127
+
128
+ def credentials?
129
+ !(@_username.nil? || @_userpass.nil?)
130
+ end
131
+ end
132
+
133
+
134
+ # #################################################
135
+ #
136
+ class CommandJSONGet
137
+ def self.call(options) # {full_url:,username:,userpass:,headers:}
138
+ new(options)
139
+ end
140
+
141
+ def json?
142
+ true
143
+ end
144
+
145
+ def uri
146
+ @_uri
147
+ end
148
+
149
+ def request
150
+ req = @_headers.nil? ? Net::HTTP::Get.new(uri.request_uri) : Net::HTTP::Get.new(uri.request_uri, @_headers) # Generate HTTPRequest object
151
+ req.basic_auth(@_username, @_userpass) if credentials?
152
+ req
153
+ end
154
+
155
+ private
156
+
157
+ def initialize(opts={})
158
+ @_username = opts[:username]
159
+ @_userpass = opts[:userpass]
160
+ @_headers = opts[:headers]
161
+ @_uri = URI.parse( opts[:full_url])
162
+ end
163
+
164
+ def credentials?
165
+ !(@_username.nil? || @_userpass.nil?)
166
+ end
167
+ end
168
+
169
+
170
+ # #################################################
171
+ #
172
+ class CommandJSONPut
173
+ def self.call(options) # {full_url:,username:,userpass:,payload:,headers:}
174
+ new(options)
175
+ end
176
+
177
+ def json?
178
+ true
179
+ end
180
+
181
+ def uri
182
+ @_uri
183
+ end
184
+
185
+ def request
186
+ req = @_headers.nil? ? Net::HTTP::Put.new(uri.path) : Net::HTTP::Put.new(uri.path, @_headers) # Generate HTTPRequest object
187
+ req.basic_auth(@_username, @_userpass) if credentials?
188
+ req.content_type = 'application/json'
189
+ req.body = formatted_data
190
+ req
191
+ end
192
+
193
+ private
194
+
195
+ def initialize(opts={})
196
+ @_username = opts[:username]
197
+ @_userpass = opts[:userpass]
198
+ @_headers = opts[:headers]
199
+ @_uri = URI.parse( opts[:full_url])
200
+ @_data = opts[:payload]
201
+ end
202
+
203
+ def formatted_data
204
+ @_data.respond_to?(:to_json) ? @_data.to_json : @_data
205
+ end
206
+
207
+ def credentials?
208
+ !(@_username.nil? || @_userpass.nil?)
209
+ end
210
+ end
211
+
212
+
213
+ # #################################################
214
+ #
215
+ class CommandFORMDelete
216
+ def self.call(options) # {full_url:,username:,userpass:}
217
+ new(options)
218
+ end
219
+
220
+ def json?
221
+ false
222
+ end
223
+
224
+ def uri
225
+ @_uri
226
+ end
227
+
228
+ def request
229
+ req = @_headers.nil? ? Net::HTTP::Delete.new(uri.request_uri) : Net::HTTP::Delete.new(uri.request_uri, @_headers) # Generate HTTPRequest object
230
+ req.basic_auth(@_username, @_userpass) if credentials?
231
+ req
232
+ end
233
+
234
+ private
235
+
236
+ def initialize(opts={})
237
+ @_username = opts[:username]
238
+ @_userpass = opts[:userpass]
239
+ @_headers = opts[:headers]
240
+ @_uri = URI.parse( opts[:full_url])
241
+ end
242
+
243
+ def credentials?
244
+ !(@_username.nil? || @_userpass.nil?)
245
+ end
246
+ end
247
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ##
2
4
  # <project.root>/lib/skn_utils/nested_result.rb
3
5
  #
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #
2
4
  #
3
5
  # Ruby Notify like class
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #
2
4
  # lib/skn_utils/null_object.rb
3
5
  #
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
 
2
4
  module SknUtils
3
5
  class PageControls < NestedResult
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
 
2
4
  module SknUtils
3
5
  class ResultBean < NestedResult
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # A better way to say it
2
4
  module SknUtils
3
5
  class Version
4
6
  MAJOR = 5
5
- MINOR = 4
7
+ MINOR = 8
6
8
  PATCH = 0
7
9
 
8
10
  def self.to_s
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ # ##
4
+ #
5
+ # Ref: https://blog.appsignal.com/2018/10/02/ruby-magic-class-level-instance-variables.html
6
+
7
+ module SknUtils
8
+
9
+ module Wrappable
10
+ def wrap(mod)
11
+ wrappers << mod
12
+ end
13
+
14
+ def wrappers
15
+ @wrappers ||= []
16
+ end
17
+
18
+ def inherited_wrappers
19
+ ancestors
20
+ .grep(Wrappable)
21
+ .reverse
22
+ .flat_map(&:wrappers)
23
+ end
24
+
25
+ def new(*arguments, &block)
26
+ instance = allocate
27
+ inherited_wrappers.each { |mod|instance.singleton_class.include(mod) }
28
+ instance.send(:initialize, *arguments, &block)
29
+ instance
30
+ end
31
+ end
32
+ end
@@ -1,44 +1,49 @@
1
+ # frozen_string_literal: true
1
2
  # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'skn_utils/version'
3
+
4
+ require_relative 'lib/skn_utils/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = 'skn_utils'
8
8
  spec.version = SknUtils::VERSION
9
9
  spec.author = 'James Scott Jr'
10
10
  spec.email = 'skoona@gmail.com'
11
- spec.summary = <<-EOF
12
- SknUtils contains a small collection of Ruby utilities, the first being a NestedResult a key/value container.
13
- EOF
14
-
15
- spec.description = <<-EOF
16
- The intent of the NestedResult class is to be a container for data values composed of key/value pairs,
17
- 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.
18
18
 
19
19
  Review the RSpec tests, and or review the README for more details.
20
- EOF
21
- spec.post_install_message = <<-EOF
20
+ DESC
21
+
22
+ spec.post_install_message = <<-DESC
22
23
  This version includes modified versions of SknUtils::ResultBean, SknUtils::PageControls classes, which inherit from
23
24
  SknUtils::NestedResult class. SknUtils::NestedResult replaces those original classes and consolidates their function.
24
- EOF
25
+ DESC
26
+
25
27
  spec.homepage = "https://github.com/skoona/skn_utils"
26
28
  spec.license = "MIT"
27
29
  spec.platform = Gem::Platform::RUBY
28
- spec.files = `git ls-files -z`.split("\x0")
30
+ spec.files = `git ls-files -z`.split("\x0")
29
31
  spec.executables = []
30
- spec.test_files = spec.files.grep(%r{^(spec)/})
31
- 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"]
32
35
 
33
36
  spec.add_runtime_dependency 'deep_merge', '~> 1'
34
37
  spec.add_runtime_dependency 'concurrent-ruby', '~> 1'
35
38
  spec.add_runtime_dependency 'thor', '~> 0'
36
39
 
37
- spec.add_development_dependency "bundler", "~> 1"
38
- spec.add_development_dependency "rake", "~> 10"
39
- spec.add_development_dependency "rspec", '~> 3'
40
- spec.add_development_dependency "pry", "~> 0"
41
- spec.add_development_dependency "simplecov", "~> 0"
42
- spec.add_development_dependency 'benchmark-ips', '~> 2'
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"
44
+ spec.add_development_dependency "pry-coolline"
45
+ spec.add_development_dependency "simplecov", ">= 0"
46
+ spec.add_development_dependency 'benchmark-ips', '>= 2'
47
+ spec.add_development_dependency 'webmock'
43
48
 
44
49
  end