Class: Wireless::Registry

Inherits:
Object
  • Object
show all
Includes:
Fetch
Defined in:
lib/wireless/registry.rb

Overview

The public API of the dependency provider (AKA service locator). A hash-like object which maps names (symbols) to dependencies (objects) via blocks which either resolve the dependency every time (factory) or once (singleton).

A class can be supplied instead of the block, in which case it is equivalent to a block which calls new on the class, e.g.:

WL = Wireless.new do
  on(:foo, Foo)
end

is equivalent to:

WL = Wireless.new do
  on(:foo) { Foo.new }
end

Constant Summary collapse

DEFAULT_EXPORTS =
{ private: [], protected: [], public: [] }
DEFAULT_VISIBILITY =
:private

Instance Method Summary collapse

Methods included from Fetch

#fetch

Constructor Details

#initialize(default_visibility = DEFAULT_VISIBILITY, &block) ⇒ Registry

Returns a new instance of Registry.



29
30
31
32
33
34
35
# File 'lib/wireless/registry.rb', line 29

def initialize(default_visibility = DEFAULT_VISIBILITY, &block)
  @default_visibility = default_visibility
  @module_cache = SynchronizedStore.new(type: :module)
  @registry = SynchronizedStore.new(type: :resolver)
  @seen = Set.new
  instance_eval(&block) if block
end

Instance Method Details

#factory(name, klass = nil, &block) ⇒ Object Also known as: on

Registers a dependency which is resolved every time its value is fetched.



38
39
40
# File 'lib/wireless/registry.rb', line 38

def factory(name, klass = nil, &block)
  @registry[name.to_sym] = Resolver::Factory.new(block || klass)
end

#include?(key) ⇒ Boolean

Returns true if a dependency with the specified name has been registered, false otherwise

Returns:

  • (Boolean)


44
45
46
# File 'lib/wireless/registry.rb', line 44

def include?(key)
  @registry.include?(key)
end

#mixin(args) ⇒ Object

Takes an array or hash specifying the dependencies to export, and returns a module which defines getters for those dependencies.

class Test
  # hash (specify visibilities)
  include Services.mixin private: :foo, protected: %i[bar baz], public: :quux

  # or an array of imports using the default visibility (:private by default)
  include Services.mixin %i[foo bar baz quux]

  def test
    foo + bar + baz + quux # access the dependencies
  end
end

The visibility of the generated getters can be controlled by passing a hash with { visibility => imports } pairs, where imports is an array of import specifiers. An import specifier is a symbol (method name == dependency name) or a hash with { dependency_name => method_name } pairs (aliases). If there’s only one import specifier, its enclosing array can be omitted, e.g.:

include Services.mixin(private: :foo, protected: { :baz => :quux })

is equivalent to:

include Services.mixin(private: [:foo], protected: [{ :baz => :quux }])


81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/wireless/registry.rb', line 81

def mixin(args)
  # normalize the supplied argument (array or hash) into a hash of
  # { visibility => exports } pairs, where `visibility` is a symbol and
  # `exports` is a hash of { dependency_name => method_name } pairs
  if args.is_a?(Array)
    args = { @default_visibility => args }
  elsif !args.is_a?(Hash)
    raise ArgumentError, "invalid mixin argument: expected array or hash, got: #{args.class}"
  end

  # slurp each array of name (symbol) or name => alias (hash) import
  # specifiers into a normalized hash of { dependency_name => method_name }
  # pairs, e.g.:
  #
  # before:
  #
  #   [:foo, { :bar => :baz }, :quux]
  #
  # after:
  #
  #   { :foo => :foo, :bar => :baz, :quux => :quux }

  # XXX transform_values requires ruby >= 2.5
  args = DEFAULT_EXPORTS.merge(args).transform_values do |exports|
    exports = [exports] unless exports.is_a?(Array)
    exports.reduce({}) do |a, b|
      a.merge(b.is_a?(Hash) ? b : { b => b })
    end
  end

  @module_cache.get!(args) { module_for(args) }
end

#singleton(name, klass = nil, &block) ⇒ Object Also known as: once

Registers a dependency which is only resolved the first time its value is fetched. On subsequent fetches, the cached value is returned.



50
51
52
# File 'lib/wireless/registry.rb', line 50

def singleton(name, klass = nil, &block)
  @registry[name.to_sym] = Resolver::Singleton.new(block || klass)
end