Basic usage
Requirements
You need only one thing before you can use dry-auto_inject: a container to hold your application’s dependencies. These are commonly known as “inversion of control” containers.
A dry-container will work well, but the only requirement is that the container responds to the #[]
interface. For example, my_container["users_repository"]
should return the “users_repository” object registered with the container.
Creating an injector
To create an injector, pass the container to Dry::AutoInject
:
Import = Dry::AutoInject(my_container)
Assign the injector to a constant (or make it globally accessible somehow) so you can refer to it from within your classes.
Specifying dependencies
To specify the dependencies for a class, mix in the injector and provide the container identifiers for each dependency:
class MyClass
include Import["users_repository", "deliver_welcome_email"]
end
Using dependencies
Each dependency is available via a reader with a matching name:
class MyClass
include Import["users_repository"]
def call
puts users_repository.inspect
end
end
If your container identifiers include delimiters (like "."
) or other characters that are not allowed within variable or method names, then the final part of the name will be used instead:
class MyClass
include Import["repositories.users"]
def call
puts users.inspect
end
end
Specifying aliases for dependencies
You can specify dependencies as a hash to provide your own names for each one:
class MyClass
include Import[users_repo: "repositories.users"]
def call
puts users_repo.inspect
end
end
If you want to provide a mix of inferred names and aliases, provide the aliases last:
class MyClass
include Import[
"repositories.users",
deliver_email: "operations.deliver_welcome_email",
]
end
Initializing your object
Initialize your object without any arguments and all the dependencies will be resolved from the the container automatically:
my_obj = MyClass.new
Passing manual dependencies
To provide an alternative object for a dependency, pass it to the initializer with a keyword argument matching the dependency’s name:
class MyClass
include Import["repositories.users"]
end
my_obj = MyClass.new(users: different_repo)
This technique is useful when testing your class in isolation. You can pass in test doubles to verify your class’ behaviour under various different circumstances.