mega-max-box 0.0.1
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 +7 -0
- data/dry-container-0.11.0/CHANGELOG.md +150 -0
- data/dry-container-0.11.0/LICENSE +20 -0
- data/dry-container-0.11.0/README.md +30 -0
- data/dry-container-0.11.0/dry-container.gemspec +37 -0
- data/dry-container-0.11.0/lib/dry/container/error.rb +15 -0
- data/dry-container-0.11.0/lib/dry/container/item/callable.rb +22 -0
- data/dry-container-0.11.0/lib/dry/container/item/factory.rb +26 -0
- data/dry-container-0.11.0/lib/dry/container/item/memoizable.rb +49 -0
- data/dry-container-0.11.0/lib/dry/container/item.rb +51 -0
- data/dry-container-0.11.0/lib/dry/container/mixin.rb +353 -0
- data/dry-container-0.11.0/lib/dry/container/namespace.rb +44 -0
- data/dry-container-0.11.0/lib/dry/container/namespace_dsl.rb +61 -0
- data/dry-container-0.11.0/lib/dry/container/registry.rb +50 -0
- data/dry-container-0.11.0/lib/dry/container/resolver.rb +88 -0
- data/dry-container-0.11.0/lib/dry/container/stub.rb +55 -0
- data/dry-container-0.11.0/lib/dry/container/version.rb +8 -0
- data/dry-container-0.11.0/lib/dry/container.rb +35 -0
- data/dry-container-0.11.0/lib/dry-container.rb +3 -0
- data/mega-max-box.gemspec +11 -0
- metadata +59 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 396b2e67ee1473e2c648652c91a0a0727d1078b780a6772c4c9252ff76da48aa
|
|
4
|
+
data.tar.gz: 33fe26afdc901065efe3fc49b3e76faabcbd2034a81cc004d14334263027391a
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 18cfcc6e655a61acb6327d8535c8a2f7b647d7d3a3131aac9432c3d223acd68a3b86728c53a0249a3dc5aa034b3b49c8f41ad76bee695c2fe2245894b321acf5
|
|
7
|
+
data.tar.gz: a0e473ca526179e70e63cf83292d4670b765dde929cb877a5fff3c37b6e86800c4a7936cab4db460f9a085dcb8de843f21997747dec6bf1f0e22fd295291d1e4
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
<!--- DO NOT EDIT THIS FILE - IT'S AUTOMATICALLY GENERATED VIA DEVTOOLS --->
|
|
2
|
+
|
|
3
|
+
## 0.11.0 2022-09-16
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Changed
|
|
7
|
+
|
|
8
|
+
- dry-configurable will be used whenever it is in the $LOAD_PATH (see dry-rb/dry-system#247 for more context) (@solnic)
|
|
9
|
+
|
|
10
|
+
[Compare v0.10.1...v0.11.0](https://github.com/dry-rb/dry-container/compare/v0.10.1...v0.11.0)
|
|
11
|
+
|
|
12
|
+
## 0.10.1 2022-07-29
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- Make `DidYouMean` integration optional (via #86) (@jbourassa)
|
|
18
|
+
|
|
19
|
+
[Compare v0.10.0...v0.10.1](https://github.com/dry-rb/dry-container/compare/v0.10.0...v0.10.1)
|
|
20
|
+
|
|
21
|
+
## 0.10.0 2022-07-10
|
|
22
|
+
|
|
23
|
+
⚠️ Notice that dry-container no longer depends on dry-configurable. If you happen to rely on the advanced configurable functionality, add dry-configurable as a dependency and require it **before** requiring dry-container.
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
|
|
27
|
+
- Accept block given to `#merge` (via #83) (@timriley)
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
|
|
31
|
+
- [BREAKING] Replace dep on dry-configurable with a simple `Configuration` mod (see #84 for more details) (@solnic)
|
|
32
|
+
- Raise KeyError for missing key, with DidYouMean integration (via #82) (@cllns)
|
|
33
|
+
- Wrap FrozenError, to state that the container itself is frozen (see #74) (@cllns)
|
|
34
|
+
|
|
35
|
+
[Compare v0.9.0...v0.10.0](https://github.com/dry-rb/dry-container/compare/v0.9.0...v0.10.0)
|
|
36
|
+
|
|
37
|
+
## 0.9.0 2021-09-12
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
### Changed
|
|
41
|
+
|
|
42
|
+
- [internal] Upgraded to new `setting` API provided in dry-configurable 0.13.0 (@timriley in #77)
|
|
43
|
+
|
|
44
|
+
[Compare v0.8.0...v0.9.0](https://github.com/dry-rb/dry-container/compare/v0.8.0...v0.9.0)
|
|
45
|
+
|
|
46
|
+
## 0.8.0 2021-06-06
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
### Changed
|
|
50
|
+
|
|
51
|
+
- [BREAKING] Support for 2.4 and 2.5 was dropped
|
|
52
|
+
|
|
53
|
+
[Compare v0.7.2...v0.8.0](https://github.com/dry-rb/dry-container/compare/v0.7.2...v0.8.0)
|
|
54
|
+
|
|
55
|
+
## 0.7.2 2019-07-09
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
### Added
|
|
59
|
+
|
|
60
|
+
- `.resolve` accepts an optional fallback block, similar to how `Hash#fetch` works ([flash-gordon](https://github.com/flash-gordon))
|
|
61
|
+
```ruby
|
|
62
|
+
container.resolve('missing_key') { :fallback } # => :fallback
|
|
63
|
+
```
|
|
64
|
+
- `.decorate` can (again) work with static values. Also, it can take a block instead of `with` ([flash-gordon](https://github.com/flash-gordon))
|
|
65
|
+
```ruby
|
|
66
|
+
container.register('key', 'value')
|
|
67
|
+
container.decorate('key') { |v| "<'#{v}'>" }
|
|
68
|
+
container.resolve('key') # => "<'value'>"
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
[Compare v0.7.1...v0.7.2](https://github.com/dry-rb/dry-container/compare/v0.7.1...v0.7.2)
|
|
73
|
+
|
|
74
|
+
## 0.7.1 2019-06-07
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
### Fixed
|
|
78
|
+
|
|
79
|
+
- Added `Mixin#dup` and `Mixin#clone`, now copies don't share underlying containers (flash-gordon)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
[Compare v0.7.0...v0.7.1](https://github.com/dry-rb/dry-container/compare/v0.7.0...v0.7.1)
|
|
83
|
+
|
|
84
|
+
## 0.7.0 2019-02-05
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
### Added
|
|
88
|
+
|
|
89
|
+
- Namespace DSL resolves keys relative to the current namespace, see the corresponding [changes](https://github.com/dry-rb/dry-container/pull/47) ([yuszuv](https://github.com/yuszuv))
|
|
90
|
+
- Registered objects can be decorated with the following API ([igor-alexandrov](https://github.com/igor-alexandrov))
|
|
91
|
+
|
|
92
|
+
```ruby
|
|
93
|
+
class CreateUser
|
|
94
|
+
def call(params)
|
|
95
|
+
# ...
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
container.register('create_user') { CreateUser.new }
|
|
99
|
+
container.decorate('create_user', with: ShinyLogger.new)
|
|
100
|
+
|
|
101
|
+
# Now subsequent resolutions will return a wrapped object
|
|
102
|
+
|
|
103
|
+
container.resolve('create_user')
|
|
104
|
+
# => #<ShinyLogger @obj=#<CreateUser:0x...>]>
|
|
105
|
+
```
|
|
106
|
+
- Freezing a container now prevents further registrations ([flash-gordon](https://github.com/flash-gordon))
|
|
107
|
+
- ## Internal
|
|
108
|
+
- Handling container items was generalized in [#34](https://github.com/dry-rb/dry-container/pull/34) ([GabrielMalakias](https://github.com/GabrielMalakias))
|
|
109
|
+
|
|
110
|
+
### Fixed
|
|
111
|
+
|
|
112
|
+
- Symbols are now coerced to strings when resolving stubbed dependencies ([cthulhu666](https://github.com/cthulhu666))
|
|
113
|
+
- Stubbing keys not present in container will raise an error ([flash-gordon](https://github.com/flash-gordon))
|
|
114
|
+
|
|
115
|
+
This means after upgrading you may see errors like this
|
|
116
|
+
```
|
|
117
|
+
ArgumentError (cannot stub "something" - no such key in container)
|
|
118
|
+
```
|
|
119
|
+
Be sure you register dependencies before using them. The new behavior will likely save quite a bit of time when debugging ill-configured container setups.
|
|
120
|
+
|
|
121
|
+
### Changed
|
|
122
|
+
|
|
123
|
+
- [BREAKING] Now only Ruby 2.3 and above is supported ([flash-gordon](https://github.com/flash-gordon))
|
|
124
|
+
|
|
125
|
+
[Compare v0.6.0...v0.7.0](https://github.com/dry-rb/dry-container/compare/v0.6.0...v0.7.0)
|
|
126
|
+
|
|
127
|
+
## 0.6.0 2016-12-09
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
### Added
|
|
131
|
+
|
|
132
|
+
- `Dry::Container::Mixin#each` - provides a means of seeing what all is registered in the container ([jeremyf](https://github.com/jeremyf))
|
|
133
|
+
|
|
134
|
+
### Fixed
|
|
135
|
+
|
|
136
|
+
- Including mixin into a class with a custom initializer ([maltoe](https://github.com/maltoe))
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
[Compare v0.5.0...v0.6.0](https://github.com/dry-rb/dry-container/compare/v0.5.0...v0.6.0)
|
|
140
|
+
|
|
141
|
+
## 0.5.0 2016-08-31
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
### Added
|
|
145
|
+
|
|
146
|
+
- `memoize` option to `#register` - memoizes items on first resolve ([ivoanjo](https://github.com/ivoanjo))
|
|
147
|
+
|
|
148
|
+
### Fixed
|
|
149
|
+
|
|
150
|
+
- `required_ruby_version` set to `>= 2.0.0` ([artofhuman](https://github.com/artofhuman))
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2015-2022 dry-rb team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
|
7
|
+
the Software without restriction, including without limitation the rights to
|
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
10
|
+
subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<!--- this file is synced from dry-rb/template-gem project -->
|
|
2
|
+
[gem]: https://rubygems.org/gems/dry-container
|
|
3
|
+
[actions]: https://github.com/dry-rb/dry-container/actions
|
|
4
|
+
[codacy]: https://www.codacy.com/gh/dry-rb/dry-container
|
|
5
|
+
[chat]: https://dry-rb.zulipchat.com
|
|
6
|
+
[inchpages]: http://inch-ci.org/github/dry-rb/dry-container
|
|
7
|
+
|
|
8
|
+
# dry-container [][chat]
|
|
9
|
+
|
|
10
|
+
[][gem]
|
|
11
|
+
[][actions]
|
|
12
|
+
[][codacy]
|
|
13
|
+
[][codacy]
|
|
14
|
+
[][inchpages]
|
|
15
|
+
|
|
16
|
+
## Links
|
|
17
|
+
|
|
18
|
+
* [User documentation](https://dry-rb.org/gems/dry-container)
|
|
19
|
+
* [API documentation](http://rubydoc.info/gems/dry-container)
|
|
20
|
+
|
|
21
|
+
## Supported Ruby versions
|
|
22
|
+
|
|
23
|
+
This library officially supports the following Ruby versions:
|
|
24
|
+
|
|
25
|
+
* MRI `>= 2.7.0`
|
|
26
|
+
* jruby `>= 9.3` (postponed until 2.7 is supported)
|
|
27
|
+
|
|
28
|
+
## License
|
|
29
|
+
|
|
30
|
+
See `LICENSE` file.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# this file is synced from dry-rb/template-gem project
|
|
4
|
+
|
|
5
|
+
lib = File.expand_path("lib", __dir__)
|
|
6
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
7
|
+
require "dry/container/version"
|
|
8
|
+
|
|
9
|
+
Gem::Specification.new do |spec|
|
|
10
|
+
spec.name = "dry-container"
|
|
11
|
+
spec.authors = ["Andy Holland"]
|
|
12
|
+
spec.email = ["andyholland1991@aol.com"]
|
|
13
|
+
spec.license = "MIT"
|
|
14
|
+
spec.version = Dry::Container::VERSION.dup
|
|
15
|
+
|
|
16
|
+
spec.summary = "A simple, configurable object container implemented in Ruby"
|
|
17
|
+
spec.description = spec.summary
|
|
18
|
+
spec.homepage = "https://dry-rb.org/gems/dry-container"
|
|
19
|
+
spec.files = Dir["CHANGELOG.md", "LICENSE", "README.md", "dry-container.gemspec", "lib/**/*"]
|
|
20
|
+
spec.bindir = "bin"
|
|
21
|
+
spec.executables = []
|
|
22
|
+
spec.require_paths = ["lib"]
|
|
23
|
+
|
|
24
|
+
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
|
25
|
+
spec.metadata["changelog_uri"] = "https://github.com/dry-rb/dry-container/blob/master/CHANGELOG.md"
|
|
26
|
+
spec.metadata["source_code_uri"] = "https://github.com/dry-rb/dry-container"
|
|
27
|
+
spec.metadata["bug_tracker_uri"] = "https://github.com/dry-rb/dry-container/issues"
|
|
28
|
+
|
|
29
|
+
spec.required_ruby_version = ">= 2.7.0"
|
|
30
|
+
|
|
31
|
+
# to update dependencies edit project.yml
|
|
32
|
+
spec.add_runtime_dependency "concurrent-ruby", "~> 1.0"
|
|
33
|
+
|
|
34
|
+
spec.add_development_dependency "bundler"
|
|
35
|
+
spec.add_development_dependency "rake"
|
|
36
|
+
spec.add_development_dependency "rspec"
|
|
37
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Dry
|
|
4
|
+
class Container
|
|
5
|
+
# @api public
|
|
6
|
+
Error = Class.new(StandardError)
|
|
7
|
+
|
|
8
|
+
KeyError = Class.new(::KeyError)
|
|
9
|
+
if defined?(DidYouMean::KeyErrorChecker)
|
|
10
|
+
DidYouMean.correct_error(KeyError, DidYouMean::KeyErrorChecker)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
deprecate_constant(:Error)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "dry/container/item"
|
|
4
|
+
|
|
5
|
+
module Dry
|
|
6
|
+
class Container
|
|
7
|
+
class Item
|
|
8
|
+
# Callable class to returns a item call
|
|
9
|
+
#
|
|
10
|
+
# @api public
|
|
11
|
+
#
|
|
12
|
+
class Callable < Item
|
|
13
|
+
# Returns the result of item call or item
|
|
14
|
+
#
|
|
15
|
+
# @return [Mixed]
|
|
16
|
+
def call
|
|
17
|
+
callable? ? item.call : item
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "dry/container/item/memoizable"
|
|
4
|
+
require "dry/container/item/callable"
|
|
5
|
+
|
|
6
|
+
module Dry
|
|
7
|
+
class Container
|
|
8
|
+
class Item
|
|
9
|
+
# Factory for create an Item to register inside of container
|
|
10
|
+
#
|
|
11
|
+
# @api public
|
|
12
|
+
class Factory
|
|
13
|
+
# Creates an Item Memoizable or Callable
|
|
14
|
+
# @param [Mixed] item
|
|
15
|
+
# @param [Hash] options
|
|
16
|
+
#
|
|
17
|
+
# @raise [Dry::Container::Error]
|
|
18
|
+
#
|
|
19
|
+
# @return [Dry::Container::Item::Base]
|
|
20
|
+
def call(item, options = {})
|
|
21
|
+
options[:memoize] ? Memoizable.new(item, options) : Callable.new(item, options)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "dry/container/item"
|
|
4
|
+
|
|
5
|
+
module Dry
|
|
6
|
+
class Container
|
|
7
|
+
class Item
|
|
8
|
+
# Memoizable class to store and execute item calls
|
|
9
|
+
#
|
|
10
|
+
# @api public
|
|
11
|
+
#
|
|
12
|
+
class Memoizable < Item
|
|
13
|
+
# @return [Mutex] the stored mutex
|
|
14
|
+
attr_reader :memoize_mutex
|
|
15
|
+
|
|
16
|
+
# Returns a new Memoizable instance
|
|
17
|
+
#
|
|
18
|
+
# @param [Mixed] item
|
|
19
|
+
# @param [Hash] options
|
|
20
|
+
#
|
|
21
|
+
# @raise [Dry::Container::Error]
|
|
22
|
+
#
|
|
23
|
+
# @return [Dry::Container::Item::Base]
|
|
24
|
+
def initialize(item, options = {})
|
|
25
|
+
super
|
|
26
|
+
raise_not_supported_error unless callable?
|
|
27
|
+
|
|
28
|
+
@memoize_mutex = ::Mutex.new
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Returns the result of item call using a syncronized mutex
|
|
32
|
+
#
|
|
33
|
+
# @return [Dry::Container::Item::Base]
|
|
34
|
+
def call
|
|
35
|
+
memoize_mutex.synchronize do
|
|
36
|
+
@memoized_item ||= item.call
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
# @private
|
|
43
|
+
def raise_not_supported_error
|
|
44
|
+
raise ::Dry::Container::Error, "Memoize only supported for a block or a proc"
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Dry
|
|
4
|
+
class Container
|
|
5
|
+
# Base class to abstract Memoizable and Callable implementations
|
|
6
|
+
#
|
|
7
|
+
# @api abstract
|
|
8
|
+
#
|
|
9
|
+
class Item
|
|
10
|
+
# @return [Mixed] the item to be solved later
|
|
11
|
+
attr_reader :item
|
|
12
|
+
|
|
13
|
+
# @return [Hash] the options to memoize, call or no.
|
|
14
|
+
attr_reader :options
|
|
15
|
+
|
|
16
|
+
# @api abstract
|
|
17
|
+
def initialize(item, options = {})
|
|
18
|
+
@item = item
|
|
19
|
+
@options = {
|
|
20
|
+
call: item.is_a?(::Proc) && item.parameters.empty?
|
|
21
|
+
}.merge(options)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# @api abstract
|
|
25
|
+
def call
|
|
26
|
+
raise NotImplementedError
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# @private
|
|
30
|
+
def value?
|
|
31
|
+
!callable?
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# @private
|
|
35
|
+
def callable?
|
|
36
|
+
options[:call]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Build a new item with transformation applied
|
|
40
|
+
#
|
|
41
|
+
# @private
|
|
42
|
+
def map(func)
|
|
43
|
+
if callable?
|
|
44
|
+
self.class.new(-> { func.(item.call) }, options)
|
|
45
|
+
else
|
|
46
|
+
self.class.new(func.(item), options)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "concurrent/hash"
|
|
4
|
+
|
|
5
|
+
module Dry
|
|
6
|
+
class Container
|
|
7
|
+
# @api public
|
|
8
|
+
class Config
|
|
9
|
+
DEFAULT_NAMESPACE_SEPARATOR = "."
|
|
10
|
+
DEFAULT_RESOLVER = Resolver.new
|
|
11
|
+
DEFAULT_REGISTRY = Registry.new
|
|
12
|
+
|
|
13
|
+
# @api public
|
|
14
|
+
attr_accessor :namespace_separator
|
|
15
|
+
|
|
16
|
+
# @api public
|
|
17
|
+
attr_accessor :resolver
|
|
18
|
+
|
|
19
|
+
# @api public
|
|
20
|
+
attr_accessor :registry
|
|
21
|
+
|
|
22
|
+
# @api private
|
|
23
|
+
def initialize(
|
|
24
|
+
namespace_separator: DEFAULT_NAMESPACE_SEPARATOR,
|
|
25
|
+
resolver: DEFAULT_RESOLVER,
|
|
26
|
+
registry: DEFAULT_REGISTRY
|
|
27
|
+
)
|
|
28
|
+
@namespace_separator = namespace_separator
|
|
29
|
+
@resolver = resolver
|
|
30
|
+
@registry = registry
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# @api public
|
|
35
|
+
module Configuration
|
|
36
|
+
# Use dry/configurable if it's available
|
|
37
|
+
begin
|
|
38
|
+
require "dry/configurable"
|
|
39
|
+
|
|
40
|
+
# @api private
|
|
41
|
+
def self.extended(klass)
|
|
42
|
+
super
|
|
43
|
+
klass.class_eval do
|
|
44
|
+
extend Dry::Configurable
|
|
45
|
+
|
|
46
|
+
setting :namespace_separator, default: Config::DEFAULT_NAMESPACE_SEPARATOR
|
|
47
|
+
setting :resolver, default: Config::DEFAULT_RESOLVER
|
|
48
|
+
setting :registry, default: Config::DEFAULT_REGISTRY
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
rescue LoadError
|
|
52
|
+
# @api private
|
|
53
|
+
def config
|
|
54
|
+
@config ||= Config.new
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# @api private
|
|
59
|
+
def configure
|
|
60
|
+
yield config
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
PREFIX_NAMESPACE = lambda do |namespace, key, config|
|
|
65
|
+
[namespace, key].join(config.namespace_separator)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
EMPTY_HASH = {}.freeze
|
|
69
|
+
|
|
70
|
+
# Mixin to expose Inversion of Control (IoC) container behaviour
|
|
71
|
+
#
|
|
72
|
+
# @example
|
|
73
|
+
#
|
|
74
|
+
# class MyClass
|
|
75
|
+
# extend Dry::Container::Mixin
|
|
76
|
+
# end
|
|
77
|
+
#
|
|
78
|
+
# MyClass.register(:item, 'item')
|
|
79
|
+
# MyClass.resolve(:item)
|
|
80
|
+
# => 'item'
|
|
81
|
+
#
|
|
82
|
+
# class MyObject
|
|
83
|
+
# include Dry::Container::Mixin
|
|
84
|
+
# end
|
|
85
|
+
#
|
|
86
|
+
# container = MyObject.new
|
|
87
|
+
# container.register(:item, 'item')
|
|
88
|
+
# container.resolve(:item)
|
|
89
|
+
# => 'item'
|
|
90
|
+
#
|
|
91
|
+
# @api public
|
|
92
|
+
#
|
|
93
|
+
# rubocop:disable Metrics/ModuleLength
|
|
94
|
+
module Mixin
|
|
95
|
+
# @private
|
|
96
|
+
def self.extended(base)
|
|
97
|
+
hooks_mod = ::Module.new do
|
|
98
|
+
def inherited(subclass)
|
|
99
|
+
subclass.instance_variable_set(:@_container, @_container.dup)
|
|
100
|
+
super
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
base.class_eval do
|
|
105
|
+
extend Configuration
|
|
106
|
+
extend hooks_mod
|
|
107
|
+
|
|
108
|
+
@_container = ::Concurrent::Hash.new
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# @private
|
|
113
|
+
module Initializer
|
|
114
|
+
def initialize(*args, &block)
|
|
115
|
+
@_container = ::Concurrent::Hash.new
|
|
116
|
+
super
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# @private
|
|
121
|
+
def self.included(base)
|
|
122
|
+
base.class_eval do
|
|
123
|
+
extend Configuration
|
|
124
|
+
prepend Initializer
|
|
125
|
+
|
|
126
|
+
def config
|
|
127
|
+
self.class.config
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Register an item with the container to be resolved later
|
|
133
|
+
#
|
|
134
|
+
# @param [Mixed] key
|
|
135
|
+
# The key to register the container item with (used to resolve)
|
|
136
|
+
# @param [Mixed] contents
|
|
137
|
+
# The item to register with the container (if no block given)
|
|
138
|
+
# @param [Hash] options
|
|
139
|
+
# Options to pass to the registry when registering the item
|
|
140
|
+
# @yield
|
|
141
|
+
# If a block is given, contents will be ignored and the block
|
|
142
|
+
# will be registered instead
|
|
143
|
+
#
|
|
144
|
+
# @return [Dry::Container::Mixin] self
|
|
145
|
+
#
|
|
146
|
+
# @api public
|
|
147
|
+
def register(key, contents = nil, options = EMPTY_HASH, &block)
|
|
148
|
+
if block_given?
|
|
149
|
+
item = block
|
|
150
|
+
options = contents if contents.is_a?(::Hash)
|
|
151
|
+
else
|
|
152
|
+
item = contents
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
config.registry.call(_container, key, item, options)
|
|
156
|
+
|
|
157
|
+
self
|
|
158
|
+
rescue FrozenError
|
|
159
|
+
raise FrozenError,
|
|
160
|
+
"can't modify frozen #{self.class} (when attempting to register '#{key}')"
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Resolve an item from the container
|
|
164
|
+
#
|
|
165
|
+
# @param [Mixed] key
|
|
166
|
+
# The key for the item you wish to resolve
|
|
167
|
+
# @yield
|
|
168
|
+
# Fallback block to call when a key is missing. Its result will be returned
|
|
169
|
+
# @yieldparam [Mixed] key Missing key
|
|
170
|
+
#
|
|
171
|
+
# @return [Mixed]
|
|
172
|
+
#
|
|
173
|
+
# @api public
|
|
174
|
+
def resolve(key, &block)
|
|
175
|
+
config.resolver.call(_container, key, &block)
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
# Resolve an item from the container
|
|
179
|
+
#
|
|
180
|
+
# @param [Mixed] key
|
|
181
|
+
# The key for the item you wish to resolve
|
|
182
|
+
#
|
|
183
|
+
# @return [Mixed]
|
|
184
|
+
#
|
|
185
|
+
# @api public
|
|
186
|
+
# @see Dry::Container::Mixin#resolve
|
|
187
|
+
def [](key)
|
|
188
|
+
resolve(key)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
# Merge in the items of the other container
|
|
192
|
+
#
|
|
193
|
+
# @param [Dry::Container] other
|
|
194
|
+
# The other container to merge in
|
|
195
|
+
# @param [Symbol, nil] namespace
|
|
196
|
+
# Namespace to prefix other container items with, defaults to nil
|
|
197
|
+
#
|
|
198
|
+
# @return [Dry::Container::Mixin] self
|
|
199
|
+
#
|
|
200
|
+
# @api public
|
|
201
|
+
def merge(other, namespace: nil, &block)
|
|
202
|
+
if namespace
|
|
203
|
+
_container.merge!(
|
|
204
|
+
other._container.each_with_object(::Concurrent::Hash.new) { |(key, item), hsh|
|
|
205
|
+
hsh[PREFIX_NAMESPACE.call(namespace, key, config)] = item
|
|
206
|
+
},
|
|
207
|
+
&block
|
|
208
|
+
)
|
|
209
|
+
else
|
|
210
|
+
_container.merge!(other._container, &block)
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
self
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
# Check whether an item is registered under the given key
|
|
217
|
+
#
|
|
218
|
+
# @param [Mixed] key
|
|
219
|
+
# The key you wish to check for registration with
|
|
220
|
+
#
|
|
221
|
+
# @return [Bool]
|
|
222
|
+
#
|
|
223
|
+
# @api public
|
|
224
|
+
def key?(key)
|
|
225
|
+
config.resolver.key?(_container, key)
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
# An array of registered names for the container
|
|
229
|
+
#
|
|
230
|
+
# @return [Array<String>]
|
|
231
|
+
#
|
|
232
|
+
# @api public
|
|
233
|
+
def keys
|
|
234
|
+
config.resolver.keys(_container)
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
# Calls block once for each key in container, passing the key as a parameter.
|
|
238
|
+
#
|
|
239
|
+
# If no block is given, an enumerator is returned instead.
|
|
240
|
+
#
|
|
241
|
+
# @return [Dry::Container::Mixin] self
|
|
242
|
+
#
|
|
243
|
+
# @api public
|
|
244
|
+
def each_key(&block)
|
|
245
|
+
config.resolver.each_key(_container, &block)
|
|
246
|
+
self
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
# Calls block once for each key/value pair in the container, passing the key and
|
|
250
|
+
# the registered item parameters.
|
|
251
|
+
#
|
|
252
|
+
# If no block is given, an enumerator is returned instead.
|
|
253
|
+
#
|
|
254
|
+
# @return [Enumerator]
|
|
255
|
+
#
|
|
256
|
+
# @api public
|
|
257
|
+
#
|
|
258
|
+
# @note In discussions with other developers, it was felt that being able to iterate
|
|
259
|
+
# over not just the registered keys, but to see what was registered would be
|
|
260
|
+
# very helpful. This is a step toward doing that.
|
|
261
|
+
def each(&block)
|
|
262
|
+
config.resolver.each(_container, &block)
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
# Decorates an item from the container with specified decorator
|
|
266
|
+
#
|
|
267
|
+
# @return [Dry::Container::Mixin] self
|
|
268
|
+
#
|
|
269
|
+
# @api public
|
|
270
|
+
def decorate(key, with: nil, &block)
|
|
271
|
+
key = key.to_s
|
|
272
|
+
original = _container.delete(key) do
|
|
273
|
+
raise Error, "Nothing registered with the key #{key.inspect}"
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
if with.is_a?(Class)
|
|
277
|
+
decorator = with.method(:new)
|
|
278
|
+
elsif block.nil? && !with.respond_to?(:call)
|
|
279
|
+
raise Error, "Decorator needs to be a Class, block, or respond to the `call` method"
|
|
280
|
+
else
|
|
281
|
+
decorator = with || block
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
_container[key] = original.map(decorator)
|
|
285
|
+
self
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
# Evaluate block and register items in namespace
|
|
289
|
+
#
|
|
290
|
+
# @param [Mixed] namespace
|
|
291
|
+
# The namespace to register items in
|
|
292
|
+
#
|
|
293
|
+
# @return [Dry::Container::Mixin] self
|
|
294
|
+
#
|
|
295
|
+
# @api public
|
|
296
|
+
def namespace(namespace, &block)
|
|
297
|
+
::Dry::Container::NamespaceDSL.new(
|
|
298
|
+
self,
|
|
299
|
+
namespace,
|
|
300
|
+
config.namespace_separator,
|
|
301
|
+
&block
|
|
302
|
+
)
|
|
303
|
+
|
|
304
|
+
self
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
# Import a namespace
|
|
308
|
+
#
|
|
309
|
+
# @param [Dry::Container::Namespace] namespace
|
|
310
|
+
# The namespace to import
|
|
311
|
+
#
|
|
312
|
+
# @return [Dry::Container::Mixin] self
|
|
313
|
+
#
|
|
314
|
+
# @api public
|
|
315
|
+
def import(namespace)
|
|
316
|
+
namespace(namespace.name, &namespace.block)
|
|
317
|
+
|
|
318
|
+
self
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
# Freeze the container. Nothing can be registered after freezing
|
|
322
|
+
#
|
|
323
|
+
# @api public
|
|
324
|
+
def freeze
|
|
325
|
+
super
|
|
326
|
+
_container.freeze
|
|
327
|
+
self
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
# @private no, really
|
|
331
|
+
def _container
|
|
332
|
+
@_container
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
# @api public
|
|
336
|
+
def dup
|
|
337
|
+
copy = super
|
|
338
|
+
copy.instance_variable_set(:@_container, _container.dup)
|
|
339
|
+
copy
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
# @api public
|
|
343
|
+
def clone
|
|
344
|
+
copy = super
|
|
345
|
+
unless copy.frozen?
|
|
346
|
+
copy.instance_variable_set(:@_container, _container.dup)
|
|
347
|
+
end
|
|
348
|
+
copy
|
|
349
|
+
end
|
|
350
|
+
end
|
|
351
|
+
# rubocop:enable Metrics/ModuleLength
|
|
352
|
+
end
|
|
353
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Dry
|
|
4
|
+
class Container
|
|
5
|
+
# Create a namespace to be imported
|
|
6
|
+
#
|
|
7
|
+
# @example
|
|
8
|
+
#
|
|
9
|
+
# ns = Dry::Container::Namespace.new('name') do
|
|
10
|
+
# register('item', 'item')
|
|
11
|
+
# end
|
|
12
|
+
#
|
|
13
|
+
# container = Dry::Container.new
|
|
14
|
+
#
|
|
15
|
+
# container.import(ns)
|
|
16
|
+
#
|
|
17
|
+
# container.resolve('name.item')
|
|
18
|
+
# => 'item'
|
|
19
|
+
#
|
|
20
|
+
#
|
|
21
|
+
# @api public
|
|
22
|
+
class Namespace
|
|
23
|
+
# @return [Mixed] The namespace (name)
|
|
24
|
+
attr_reader :name
|
|
25
|
+
# @return [Proc] The block to be executed when the namespace is imported
|
|
26
|
+
attr_reader :block
|
|
27
|
+
|
|
28
|
+
# Create a new namespace
|
|
29
|
+
#
|
|
30
|
+
# @param [Mixed] name
|
|
31
|
+
# The name of the namespace
|
|
32
|
+
# @yield
|
|
33
|
+
# The block to evaluate when the namespace is imported
|
|
34
|
+
#
|
|
35
|
+
# @return [Dry::Container::Namespace]
|
|
36
|
+
#
|
|
37
|
+
# @api public
|
|
38
|
+
def initialize(name, &block)
|
|
39
|
+
@name = name
|
|
40
|
+
@block = block
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "delegate"
|
|
4
|
+
|
|
5
|
+
module Dry
|
|
6
|
+
class Container
|
|
7
|
+
# @api private
|
|
8
|
+
class NamespaceDSL < ::SimpleDelegator
|
|
9
|
+
# DSL for defining namespaces
|
|
10
|
+
#
|
|
11
|
+
# @param [Dry::Container::Mixin] container
|
|
12
|
+
# The container
|
|
13
|
+
# @param [String] namespace
|
|
14
|
+
# The namespace (name)
|
|
15
|
+
# @param [String] namespace_separator
|
|
16
|
+
# The namespace separator
|
|
17
|
+
# @yield
|
|
18
|
+
# The block to evaluate to define the namespace
|
|
19
|
+
#
|
|
20
|
+
# @return [Mixed]
|
|
21
|
+
#
|
|
22
|
+
# @api private
|
|
23
|
+
def initialize(container, namespace, namespace_separator, &block)
|
|
24
|
+
@namespace = namespace
|
|
25
|
+
@namespace_separator = namespace_separator
|
|
26
|
+
|
|
27
|
+
super(container)
|
|
28
|
+
|
|
29
|
+
if block.arity.zero?
|
|
30
|
+
instance_eval(&block)
|
|
31
|
+
else
|
|
32
|
+
yield self
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def register(key, *args, &block)
|
|
37
|
+
super(namespaced(key), *args, &block)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def namespace(namespace, &block)
|
|
41
|
+
super(namespaced(namespace), &block)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def import(namespace)
|
|
45
|
+
namespace(namespace.name, &namespace.block)
|
|
46
|
+
|
|
47
|
+
self
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def resolve(key)
|
|
51
|
+
super(namespaced(key))
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
def namespaced(key)
|
|
57
|
+
[@namespace, key].join(@namespace_separator)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "dry/container/item/factory"
|
|
4
|
+
|
|
5
|
+
module Dry
|
|
6
|
+
class Container
|
|
7
|
+
# Default registry for registering items with the container
|
|
8
|
+
#
|
|
9
|
+
# @api public
|
|
10
|
+
class Registry
|
|
11
|
+
# @private
|
|
12
|
+
def initialize
|
|
13
|
+
@_mutex = ::Mutex.new
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Register an item with the container to be resolved later
|
|
17
|
+
#
|
|
18
|
+
# @param [Concurrent::Hash] container
|
|
19
|
+
# The container
|
|
20
|
+
# @param [Mixed] key
|
|
21
|
+
# The key to register the container item with (used to resolve)
|
|
22
|
+
# @param [Mixed] item
|
|
23
|
+
# The item to register with the container
|
|
24
|
+
# @param [Hash] options
|
|
25
|
+
# @option options [Symbol] :call
|
|
26
|
+
# Whether the item should be called when resolved
|
|
27
|
+
#
|
|
28
|
+
# @raise [Dry::Container::Error]
|
|
29
|
+
# If an item is already registered with the given key
|
|
30
|
+
#
|
|
31
|
+
# @return [Mixed]
|
|
32
|
+
#
|
|
33
|
+
# @api public
|
|
34
|
+
def call(container, key, item, options)
|
|
35
|
+
key = key.to_s.dup.freeze
|
|
36
|
+
@_mutex.synchronize do
|
|
37
|
+
if container.key?(key)
|
|
38
|
+
raise Error, "There is already an item registered with the key #{key.inspect}"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
container[key] = factory.call(item, options)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def factory
|
|
46
|
+
@factory ||= ::Dry::Container::Item::Factory.new
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Dry
|
|
4
|
+
class Container
|
|
5
|
+
# Default resolver for resolving items from container
|
|
6
|
+
#
|
|
7
|
+
# @api public
|
|
8
|
+
class Resolver
|
|
9
|
+
# Resolve an item from the container
|
|
10
|
+
#
|
|
11
|
+
# @param [Concurrent::Hash] container
|
|
12
|
+
# The container
|
|
13
|
+
# @param [Mixed] key
|
|
14
|
+
# The key for the item you wish to resolve
|
|
15
|
+
# @yield
|
|
16
|
+
# Fallback block to call when a key is missing. Its result will be returned
|
|
17
|
+
# @yieldparam [Mixed] key Missing key
|
|
18
|
+
#
|
|
19
|
+
# @raise [KeyError]
|
|
20
|
+
# If the given key is not registered with the container (and no block provided)
|
|
21
|
+
#
|
|
22
|
+
#
|
|
23
|
+
# @return [Mixed]
|
|
24
|
+
#
|
|
25
|
+
# @api public
|
|
26
|
+
def call(container, key)
|
|
27
|
+
item = container.fetch(key.to_s) do
|
|
28
|
+
if block_given?
|
|
29
|
+
return yield(key)
|
|
30
|
+
else
|
|
31
|
+
raise KeyError.new(%(key not found: "#{key}"), key: key.to_s, receiver: container)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
item.call
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Check whether an items is registered under the given key
|
|
39
|
+
#
|
|
40
|
+
# @param [Concurrent::Hash] container
|
|
41
|
+
# The container
|
|
42
|
+
# @param [Mixed] key
|
|
43
|
+
# The key you wish to check for registration with
|
|
44
|
+
#
|
|
45
|
+
# @return [Bool]
|
|
46
|
+
#
|
|
47
|
+
# @api public
|
|
48
|
+
def key?(container, key)
|
|
49
|
+
container.key?(key.to_s)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# An array of registered names for the container
|
|
53
|
+
#
|
|
54
|
+
# @return [Array]
|
|
55
|
+
#
|
|
56
|
+
# @api public
|
|
57
|
+
def keys(container)
|
|
58
|
+
container.keys
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Calls block once for each key in container, passing the key as a parameter.
|
|
62
|
+
#
|
|
63
|
+
# If no block is given, an enumerator is returned instead.
|
|
64
|
+
#
|
|
65
|
+
# @return Hash
|
|
66
|
+
#
|
|
67
|
+
# @api public
|
|
68
|
+
def each_key(container, &block)
|
|
69
|
+
container.each_key(&block)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Calls block once for each key in container, passing the key and
|
|
73
|
+
# the registered item parameters.
|
|
74
|
+
#
|
|
75
|
+
# If no block is given, an enumerator is returned instead.
|
|
76
|
+
#
|
|
77
|
+
# @return Key, Value
|
|
78
|
+
#
|
|
79
|
+
# @api public
|
|
80
|
+
# @note In discussions with other developers, it was felt that being able
|
|
81
|
+
# to iterate over not just the registered keys, but to see what was
|
|
82
|
+
# registered would be very helpful. This is a step toward doing that.
|
|
83
|
+
def each(container, &block)
|
|
84
|
+
container.map { |key, value| [key, value.call] }.each(&block)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Dry
|
|
4
|
+
class Container
|
|
5
|
+
module Stub
|
|
6
|
+
# Overrides resolve to look into stubbed keys first
|
|
7
|
+
#
|
|
8
|
+
# @api public
|
|
9
|
+
def resolve(key)
|
|
10
|
+
_stubs.fetch(key.to_s) { super }
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Add a stub to the container
|
|
14
|
+
def stub(key, value, &block)
|
|
15
|
+
unless key?(key)
|
|
16
|
+
raise ArgumentError, "cannot stub #{key.to_s.inspect} - no such key in container"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
_stubs[key.to_s] = value
|
|
20
|
+
|
|
21
|
+
if block
|
|
22
|
+
yield
|
|
23
|
+
unstub(key)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
self
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Remove stubbed keys from the container
|
|
30
|
+
def unstub(*keys)
|
|
31
|
+
keys = _stubs.keys if keys.empty?
|
|
32
|
+
keys.each { |key| _stubs.delete(key.to_s) }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Stubs have already been enabled turning this into a noop
|
|
36
|
+
def enable_stubs!
|
|
37
|
+
# DO NOTHING
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
# Stubs container
|
|
43
|
+
def _stubs
|
|
44
|
+
@_stubs ||= {}
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
module Mixin
|
|
49
|
+
# Enable stubbing functionality into the current container
|
|
50
|
+
def enable_stubs!
|
|
51
|
+
extend ::Dry::Container::Stub
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "dry/container/error"
|
|
4
|
+
require "dry/container/namespace"
|
|
5
|
+
require "dry/container/registry"
|
|
6
|
+
require "dry/container/resolver"
|
|
7
|
+
require "dry/container/namespace_dsl"
|
|
8
|
+
require "dry/container/mixin"
|
|
9
|
+
require "dry/container/version"
|
|
10
|
+
|
|
11
|
+
# A collection of micro-libraries, each intended to encapsulate
|
|
12
|
+
# a common task in Ruby
|
|
13
|
+
module Dry
|
|
14
|
+
# Inversion of Control (IoC) container
|
|
15
|
+
#
|
|
16
|
+
# @example
|
|
17
|
+
#
|
|
18
|
+
# container = Dry::Container.new
|
|
19
|
+
# container.register(:item, 'item')
|
|
20
|
+
# container.resolve(:item)
|
|
21
|
+
# => 'item'
|
|
22
|
+
#
|
|
23
|
+
# container.register(:item1, -> { 'item' })
|
|
24
|
+
# container.resolve(:item1)
|
|
25
|
+
# => 'item'
|
|
26
|
+
#
|
|
27
|
+
# container.register(:item2, -> { 'item' }, call: false)
|
|
28
|
+
# container.resolve(:item2)
|
|
29
|
+
# => #<Proc:0x007f33b169e998@(irb):10 (lambda)>
|
|
30
|
+
#
|
|
31
|
+
# @api public
|
|
32
|
+
class Container
|
|
33
|
+
include ::Dry::Container::Mixin
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Gem::Specification.new do |s|
|
|
2
|
+
s.name = "mega-max-box"
|
|
3
|
+
s.version = "0.0.1"
|
|
4
|
+
s.summary = "Research test"
|
|
5
|
+
s.description = "University research based on dry-container"
|
|
6
|
+
s.authors = ["Andrey78"]
|
|
7
|
+
s.email = ["cakoc614@gmail.com"]
|
|
8
|
+
s.files = Dir.glob("**/*").reject { |f| f.end_with?('.gem') }
|
|
9
|
+
s.homepage = "https://rubygems.org/profiles/Andrey78"
|
|
10
|
+
s.license = "MIT"
|
|
11
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: mega-max-box
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Andrey78
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 2026-07-06 00:00:00.000000000 Z
|
|
11
|
+
dependencies: []
|
|
12
|
+
description: University research based on dry-container
|
|
13
|
+
email:
|
|
14
|
+
- cakoc614@gmail.com
|
|
15
|
+
executables: []
|
|
16
|
+
extensions: []
|
|
17
|
+
extra_rdoc_files: []
|
|
18
|
+
files:
|
|
19
|
+
- dry-container-0.11.0/CHANGELOG.md
|
|
20
|
+
- dry-container-0.11.0/LICENSE
|
|
21
|
+
- dry-container-0.11.0/README.md
|
|
22
|
+
- dry-container-0.11.0/dry-container.gemspec
|
|
23
|
+
- dry-container-0.11.0/lib/dry-container.rb
|
|
24
|
+
- dry-container-0.11.0/lib/dry/container.rb
|
|
25
|
+
- dry-container-0.11.0/lib/dry/container/error.rb
|
|
26
|
+
- dry-container-0.11.0/lib/dry/container/item.rb
|
|
27
|
+
- dry-container-0.11.0/lib/dry/container/item/callable.rb
|
|
28
|
+
- dry-container-0.11.0/lib/dry/container/item/factory.rb
|
|
29
|
+
- dry-container-0.11.0/lib/dry/container/item/memoizable.rb
|
|
30
|
+
- dry-container-0.11.0/lib/dry/container/mixin.rb
|
|
31
|
+
- dry-container-0.11.0/lib/dry/container/namespace.rb
|
|
32
|
+
- dry-container-0.11.0/lib/dry/container/namespace_dsl.rb
|
|
33
|
+
- dry-container-0.11.0/lib/dry/container/registry.rb
|
|
34
|
+
- dry-container-0.11.0/lib/dry/container/resolver.rb
|
|
35
|
+
- dry-container-0.11.0/lib/dry/container/stub.rb
|
|
36
|
+
- dry-container-0.11.0/lib/dry/container/version.rb
|
|
37
|
+
- mega-max-box.gemspec
|
|
38
|
+
homepage: https://rubygems.org/profiles/Andrey78
|
|
39
|
+
licenses:
|
|
40
|
+
- MIT
|
|
41
|
+
metadata: {}
|
|
42
|
+
rdoc_options: []
|
|
43
|
+
require_paths:
|
|
44
|
+
- lib
|
|
45
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
46
|
+
requirements:
|
|
47
|
+
- - ">="
|
|
48
|
+
- !ruby/object:Gem::Version
|
|
49
|
+
version: '0'
|
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ">="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0'
|
|
55
|
+
requirements: []
|
|
56
|
+
rubygems_version: 3.6.2
|
|
57
|
+
specification_version: 4
|
|
58
|
+
summary: Research test
|
|
59
|
+
test_files: []
|