skn_utils 5.7.0 → 5.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|
-
[](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
|
-
```
|