lib/dry/container/mixin.rb in dry-container-0.9.0 vs lib/dry/container/mixin.rb in dry-container-0.10.0
- old
+ new
@@ -2,10 +2,65 @@
require "concurrent/hash"
module Dry
class Container
+ # @api public
+ class Config
+ DEFAULT_NAMESPACE_SEPARATOR = "."
+ DEFAULT_RESOLVER = Resolver.new
+ DEFAULT_REGISTRY = Registry.new
+
+ # @api public
+ attr_accessor :namespace_separator
+
+ # @api public
+ attr_accessor :resolver
+
+ # @api public
+ attr_accessor :registry
+
+ # @api private
+ def initialize(
+ namespace_separator: DEFAULT_NAMESPACE_SEPARATOR,
+ resolver: DEFAULT_RESOLVER,
+ registry: DEFAULT_REGISTRY
+ )
+ @namespace_separator = namespace_separator
+ @resolver = resolver
+ @registry = registry
+ end
+ end
+
+ # @api public
+ module Configuration
+ # Use dry/configurable if it's available
+ if defined?(Configurable)
+ # @api private
+ def self.extended(klass)
+ super
+ klass.class_eval do
+ extend Dry::Configurable
+
+ setting :namespace_separator, default: Config::DEFAULT_NAMESPACE_SEPARATOR
+ setting :resolver, default: Config::DEFAULT_RESOLVER
+ setting :registry, default: Config::DEFAULT_REGISTRY
+ end
+ end
+ else
+ # @api private
+ def config
+ @config ||= Config.new
+ end
+ end
+
+ # @api private
+ def configure
+ yield config
+ end
+ end
+
PREFIX_NAMESPACE = lambda do |namespace, key, config|
[namespace, key].join(config.namespace_separator)
end
EMPTY_HASH = {}.freeze
@@ -29,11 +84,10 @@
# container = MyObject.new
# container.register(:item, 'item')
# container.resolve(:item)
# => 'item'
#
- #
# @api public
module Mixin
# @private
def self.extended(base)
hooks_mod = ::Module.new do
@@ -42,17 +96,13 @@
super
end
end
base.class_eval do
- extend ::Dry::Configurable
+ extend Configuration
extend hooks_mod
- setting :registry, default: Dry::Container::Registry.new
- setting :resolver, default: Dry::Container::Resolver.new
- setting :namespace_separator, default: "."
-
@_container = ::Concurrent::Hash.new
end
end
# @private
@@ -64,17 +114,13 @@
end
# @private
def self.included(base)
base.class_eval do
- extend ::Dry::Configurable
+ extend Configuration
prepend Initializer
- setting :registry, default: Dry::Container::Registry.new
- setting :resolver, default: Dry::Container::Resolver.new
- setting :namespace_separator, default: "."
-
def config
self.class.config
end
end
end
@@ -103,10 +149,13 @@
end
config.registry.call(_container, key, item, options)
self
+ rescue FrozenError
+ raise FrozenError,
+ "can't modify frozen #{self.class} (when attempting to register '#{key}')"
end
# Resolve an item from the container
#
# @param [Mixed] key
@@ -143,19 +192,20 @@
# Namespace to prefix other container items with, defaults to nil
#
# @return [Dry::Container::Mixin] self
#
# @api public
- def merge(other, namespace: nil)
+ def merge(other, namespace: nil, &block)
if namespace
_container.merge!(
- other._container.each_with_object(::Concurrent::Hash.new) do |a, h|
- h[PREFIX_NAMESPACE.call(namespace, a.first, config)] = a.last
- end
+ other._container.each_with_object(::Concurrent::Hash.new) { |(key, item), hsh|
+ hsh[PREFIX_NAMESPACE.call(namespace, key, config)] = item
+ },
+ &block
)
else
- _container.merge!(other._container)
+ _container.merge!(other._container, &block)
end
self
end
@@ -190,21 +240,22 @@
def each_key(&block)
config.resolver.each_key(_container, &block)
self
end
- # Calls block once for each key/value pair in the container, passing the key and the registered item parameters.
+ # Calls block once for each key/value pair in the container, passing the key and
+ # the registered item parameters.
#
# If no block is given, an enumerator is returned instead.
#
# @return [Enumerator]
#
# @api public
#
- # @note In discussions with other developers, it was felt that being able to iterate over not just
- # the registered keys, but to see what was registered would be very helpful. This is a step
- # toward doing that.
+ # @note In discussions with other developers, it was felt that being able to iterate
+ # over not just the registered keys, but to see what was registered would be
+ # very helpful. This is a step toward doing that.
def each(&block)
config.resolver.each(_container, &block)
end
# Decorates an item from the container with specified decorator
@@ -291,7 +342,8 @@
copy.instance_variable_set(:@_container, _container.dup)
end
copy
end
end
+ # rubocop: enable Metrics/ModuleLength
end
end