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 +5 -5
- data/README.md +61 -46
- data/_config.yml +4 -4
- data/lib/skn_utils/concurrent_jobs.rb +16 -4
- data/lib/skn_utils/configurable.rb +1 -0
- data/lib/skn_utils/job_commands.rb +41 -0
- data/lib/skn_utils/version.rb +1 -1
- data/skn_utils.gemspec +25 -24
- metadata +27 -24
- data/README.rdoc +0 -379
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: bdbe2b2318e4841c25afdec1e118cc19ff445f8a8b1e08d116715f5b9df0f56e
|
4
|
+
data.tar.gz: d42c5e55def5f8c2789714d1fada2f341f59665ba633192732b9e6b48816e253
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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/
|
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
|
-
|
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
|
224
|
-
SknUtils::ResultBean # Wrapper
|
225
|
-
SknUtils::PageControls # Wrapper
|
226
|
-
SknUtils::DottedHash # Wrapper
|
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
|
-
|
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
|
-
|
219
|
+
SknUtils::Configurable # Add Class writers/getters to any Class, think class configuration
|
231
220
|
|
232
|
-
SknContainer/SknRegistry #
|
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
|
-
|
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
|
314
|
-
|
315
|
-
|
316
|
-
|
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})
|
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
|
-
|
327
|
-
|
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(:
|
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
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
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
|
-
|
363
|
-
|
364
|
-
|
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
|
-
|
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={})
|
data/_config.yml
CHANGED
@@ -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
|
-
|
5
|
-
|
6
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
#
|
data/lib/skn_utils/version.rb
CHANGED
data/skn_utils.gemspec
CHANGED
@@ -1,48 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
# coding: utf-8
|
2
|
-
|
3
|
-
|
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 = <<-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
-
|
22
|
-
|
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
|
-
|
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
|
30
|
+
spec.files = `git ls-files -z`.split("\x0")
|
30
31
|
spec.executables = []
|
31
|
-
spec.test_files
|
32
|
-
spec.require_paths = [
|
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", "
|
39
|
-
spec.add_development_dependency "rake", "
|
40
|
-
spec.add_development_dependency "rspec", '
|
41
|
-
spec.add_development_dependency "pry", "
|
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", "
|
44
|
-
spec.add_development_dependency 'benchmark-ips', '
|
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.
|
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-
|
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:
|
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:
|
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: "
|
168
|
-
|
169
|
-
|
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.
|
272
|
+
rubygems_version: 2.7.9
|
270
273
|
signing_key:
|
271
274
|
specification_version: 4
|
272
|
-
summary:
|
273
|
-
|
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
|
data/README.rdoc
DELETED
@@ -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
|
-
```
|