Module: Dry::Container::Mixin

Included in:
Dry::Container
Defined in:
lib/dry/container/mixin.rb,
lib/dry/container/stub.rb

Overview

Mixin to expose Inversion of Control (IoC) container behaviour

rubocop:disable Metrics/ModuleLength

Examples:


class MyClass
  extend Dry::Container::Mixin
end

MyClass.register(:item, 'item')
MyClass.resolve(:item)
=> 'item'

class MyObject
  include Dry::Container::Mixin
end

container = MyObject.new
container.register(:item, 'item')
container.resolve(:item)
=> 'item'

Defined Under Namespace

Modules: Initializer

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.extended(base) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/dry/container/mixin.rb', line 96

def self.extended(base)
  hooks_mod = ::Module.new do
    def inherited(subclass)
      subclass.instance_variable_set(:@_container, @_container.dup)
      super
    end
  end

  base.class_eval do
    extend Configuration
    extend hooks_mod

    @_container = ::Concurrent::Hash.new
  end
end

.included(base) ⇒ Object



121
122
123
124
125
126
127
128
129
130
# File 'lib/dry/container/mixin.rb', line 121

def self.included(base)
  base.class_eval do
    extend Configuration
    prepend Initializer

    def config
      self.class.config
    end
  end
end

Instance Method Details

#[](key) ⇒ Mixed

Resolve an item from the container

Parameters:

  • key (Mixed)

    The key for the item you wish to resolve

Returns:

  • (Mixed)

See Also:



187
188
189
# File 'lib/dry/container/mixin.rb', line 187

def [](key)
  resolve(key)
end

#_containerObject



331
332
333
# File 'lib/dry/container/mixin.rb', line 331

def _container
  @_container
end

#cloneObject



343
344
345
346
347
348
349
# File 'lib/dry/container/mixin.rb', line 343

def clone
  copy = super
  unless copy.frozen?
    copy.instance_variable_set(:@_container, _container.dup)
  end
  copy
end

#decorate(key, with: nil, &block) ⇒ Dry::Container::Mixin

Decorates an item from the container with specified decorator

Returns:



270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
# File 'lib/dry/container/mixin.rb', line 270

def decorate(key, with: nil, &block)
  key = key.to_s
  original = _container.delete(key) do
    raise Error, "Nothing registered with the key #{key.inspect}"
  end

  if with.is_a?(Class)
    decorator = with.method(:new)
  elsif block.nil? && !with.respond_to?(:call)
    raise Error, "Decorator needs to be a Class, block, or respond to the `call` method"
  else
    decorator = with || block
  end

  _container[key] = original.map(decorator)
  self
end

#dupObject



336
337
338
339
340
# File 'lib/dry/container/mixin.rb', line 336

def dup
  copy = super
  copy.instance_variable_set(:@_container, _container.dup)
  copy
end

#each(&block) ⇒ Enumerator

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.

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.

Returns:

  • (Enumerator)


261
262
263
# File 'lib/dry/container/mixin.rb', line 261

def each(&block)
  config.resolver.each(_container, &block)
end

#each_key(&block) ⇒ Dry::Container::Mixin

Calls block once for each key in container, passing the key as a parameter.

If no block is given, an enumerator is returned instead.

Returns:



244
245
246
247
# File 'lib/dry/container/mixin.rb', line 244

def each_key(&block)
  config.resolver.each_key(_container, &block)
  self
end

#enable_stubs!Object

Enable stubbing functionality into the current container



50
51
52
# File 'lib/dry/container/stub.rb', line 50

def enable_stubs!
  extend ::Dry::Container::Stub
end

#freezeObject

Freeze the container. Nothing can be registered after freezing



324
325
326
327
328
# File 'lib/dry/container/mixin.rb', line 324

def freeze
  super
  _container.freeze
  self
end

#import(namespace) ⇒ Dry::Container::Mixin

Import a namespace

Parameters:

Returns:



315
316
317
318
319
# File 'lib/dry/container/mixin.rb', line 315

def import(namespace)
  namespace(namespace.name, &namespace.block)

  self
end

#key?(key) ⇒ Bool

Check whether an item is registered under the given key

Parameters:

  • key (Mixed)

    The key you wish to check for registration with

Returns:

  • (Bool)


224
225
226
# File 'lib/dry/container/mixin.rb', line 224

def key?(key)
  config.resolver.key?(_container, key)
end

#keysArray<String>

An array of registered names for the container

Returns:

  • (Array<String>)


233
234
235
# File 'lib/dry/container/mixin.rb', line 233

def keys
  config.resolver.keys(_container)
end

#merge(other, namespace: nil, &block) ⇒ Dry::Container::Mixin

Merge in the items of the other container

Parameters:

  • other (Dry::Container)

    The other container to merge in

  • namespace (Symbol, nil) (defaults to: nil)

    Namespace to prefix other container items with, defaults to nil

Returns:



201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/dry/container/mixin.rb', line 201

def merge(other, namespace: nil, &block)
  if namespace
    _container.merge!(
      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, &block)
  end

  self
end

#namespace(namespace, &block) ⇒ Dry::Container::Mixin

Evaluate block and register items in namespace

Parameters:

  • namespace (Mixed)

    The namespace to register items in

Returns:



296
297
298
299
300
301
302
303
304
305
# File 'lib/dry/container/mixin.rb', line 296

def namespace(namespace, &block)
  ::Dry::Container::NamespaceDSL.new(
    self,
    namespace,
    config.namespace_separator,
    &block
  )

  self
end

#register(key, contents = nil, options = EMPTY_HASH) { ... } ⇒ Dry::Container::Mixin

Register an item with the container to be resolved later

Parameters:

  • key (Mixed)

    The key to register the container item with (used to resolve)

  • contents (Mixed) (defaults to: nil)

    The item to register with the container (if no block given)

  • options (Hash) (defaults to: EMPTY_HASH)

    Options to pass to the registry when registering the item

Yields:

  • If a block is given, contents will be ignored and the block will be registered instead

Returns:



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/dry/container/mixin.rb', line 147

def register(key, contents = nil, options = EMPTY_HASH, &block)
  if block_given?
    item = block
    options = contents if contents.is_a?(::Hash)
  else
    item = contents
  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(key) {|key| ... } ⇒ Mixed

Resolve an item from the container

Parameters:

  • key (Mixed)

    The key for the item you wish to resolve

Yields:

  • Fallback block to call when a key is missing. Its result will be returned

Yield Parameters:

  • key (Mixed)

    Missing key

Returns:

  • (Mixed)


174
175
176
# File 'lib/dry/container/mixin.rb', line 174

def resolve(key, &block)
  config.resolver.call(_container, key, &block)
end