module Flows::Plugin::DependencyInjector

Allows to inject dependencies on the initialization step.

After including this module you inject dependencies by providing `:dependencies` key to your initializer:

x = MyClass.new(dependencies: { my_dep: -> { 'Hi' } })
x.my_dep
# => 'Hi'

Keys are dependency names. Dependency will be injected as a public method with dependency name. Values are dependencies itself.

You can also require some dependencies to be present. If required dependency is missed - {MissingDependencyError} will be raised.

If an optional dependency has no default - {MissingDependencyDefaultError} will be raised.

For an optional dependency default value must be provided.

You can provide a type for the dependency. Type check uses case equality (`===`). So, it works like Ruby's `case`. In case of type mismatch {UnexpectedDependencyTypeError} will be raised.

dependency :name, type: String # name should be a string

# by the way, you can use lambdas like in Ruby's `case`
dependency :age, type: ->(x) { x.is_a?(Number) && x > 0 && x < 100 }

If you're trying to inject undeclared dependency - {UnexpectedDependencyError} will be raised.

Inheritance is supported and dependency definitions will be inherited into child classes.

@example

class MyClass
  include Flows::Plugin::DependencyInjector

  dependency :logger, required: true
  dependency :name, default: 'Boris', type: String # by default dependency is optional.

  attr_reader :data

  def initializer(data)
    @data = data
  end

  def log_the_name
    logger.call(name)
  end
end

class Logger
  def self.call(msg)
    puts msg
  end
end

x = MyClass.new('DATA', dependencies: {
  logger: Logger
})

x.data
# => 'DATA'

x.name
# => 'Boris'

x.logger.call('Hello')
# prints 'Hello'

x.log_the_name
# prints 'Boris'

Constants

Dependency

Resolves dependency on initialization and can inject it into class instance.

@api private

DependencyDefinition

Struct for storing dependency definitions.

@api private

InitializerWrapper
NO_DEFAULT

Placeholder for empty default. We cannot use `nil` because value can be `nil`.

NO_TYPE

Placeholder for empty type. We cannot use `nil` because value can be `nil`.

NO_VALUE

Placeholder for empty value. We cannot use `nil` because value can be `nil`.

SingletonVarsSetup