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 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 [![Join the chat at https://dry-rb.zulipchat.com](https://img.shields.io/badge/dry--rb-join%20chat-%23346b7a.svg)][chat]
9
+
10
+ [![Gem Version](https://badge.fury.io/rb/dry-container.svg)][gem]
11
+ [![CI Status](https://github.com/dry-rb/dry-container/workflows/ci/badge.svg)][actions]
12
+ [![Codacy Badge](https://api.codacy.com/project/badge/Grade/227509c9034340b493f769f6277f4ecb)][codacy]
13
+ [![Codacy Badge](https://api.codacy.com/project/badge/Coverage/227509c9034340b493f769f6277f4ecb)][codacy]
14
+ [![Inline docs](http://inch-ci.org/github/dry-rb/dry-container.svg?branch=main)][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,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dry
4
+ class Container
5
+ # @api public
6
+ VERSION = "0.11.0"
7
+ end
8
+ 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,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/container"
@@ -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: []