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