Automatic Dependency Injection where you get to see and keep control of the constructor.
Inject a dependency:
class MyClass
include LowType
def initialize(my_dependency: Dependency)
@my_dependency = my_dependency # => The dependency is injected.
end
endThe above example requires LowType in order to use the def(dependency: Dependency) syntax.
Or you may like to use the more traditional include syntax:
class MyClass
include LowDependency[:my_dependency]
def my_method
@my_dependency # => The dependency is injected.
end
endThis method hides and creates the constructor on your behalf.
Provide the dependency with:
LowDependency.provide(:my_dependency) do
MyDependency.new
endNamespaced string keys are fine too:
LowDependency.provide('billing.payment_provider') do
PaymentProvider.new
endLowDependency lets you do something special; mix "classical" dependency injection (passing an arg to new) with "automatic" style dependency injection (populating an arg via a provider):
# Define both an "automatic" and a "classical" dependency:
class MyClass
include LowType
def initialize(automatic_dependency: Dependency, classical_dependency:)
@automatic_dependency = automatic_dependency
@classical_dependency = classical_dependency
end
end
# Now bring it all together by calling:
MyClass.new(classical_dependency: ClassicalDependency.new)The automatic_dependency argument will automatically be injected by LowDependency!
Now you get to have your classical dependency cake 🍰 and eat it too with an automatically injected dependency spoon 🥣
The def(dependency: Dependency) syntax is an Expression; an object composed via a query builder like interface. A Dependency Expression defines the name of the local variable, as well as the name of the provider that will inject the dependency into your code.
To define a provider with a different name to that of the local variable do:
def initialize(dependency_one: Dependency | :provider_one, dependency_two: Dependency | 'billing.provider_two')
dependency_one # => Dependency injected from :provider_one.
dependency_two # => Dependency injected from 'billing.provider_two'.
endℹ️ The value after the pipe | becomes the provider key. When the provider key is omitted then the name of the positional/keyword argument is substituted as the provider key instead.
The include style syntax supports the same functionallity as the dependency expression syntax.
Multiple dependencies:
class MyClass
include LowDependency[:dependency_one, :dependency_two]
endDependencies with differing local variable/provider keys:
class MyClass
include LowDependency[dependency_one: :provider_one, dependency_two: 'billing.provider_two']
# Instance variables @dependency_one and @dependency_two are now available.
endSeparating many dependencies on multiple lines:
class MyClass
include LowDependency[
dependency_one: :provider_one,
dependency_two: 'billing.provider_two',
:dependency_three,
:four_dependencies_is_still_quite_reasonable_yeah,
]
endAdd gem 'low_dependency' to your Gemfile then:
bundle install