Medicine
Simple Dependency Injection for Ruby
Find yourself injecting dependencies via the initalizer or a setter method?
Medicine makes this declarative.
Usage
Include the Medicine module and declare the dependencies with dependency
.
class CastVote
include Medicine.di
dependency :votes_repo, default: -> { Vote }
def call
votes_repo # => Vote
end
end
For each dependency declared a private method is defined which returns the dependency.
Without injection
command = CastVote.new
In the above case the votes_repo
method will return Vote
.
If no dependency is injected the default will be used.
Specifying a default is optional and if a dependency is not injected and there is no default an error will be raised if the dependencies method is invoked.
Injecting via initializer
command = CastVote.new(votes_repo: double)
In the above case votes_repo
will return the double.
If you try and inject a dependency which has not been declared an error is raised.
Injecting via a setter
command = CastVote.new
command.inject_depdendency(:vote_repo, double)
In the above case votes_repo
will return the double.
If you try and inject a dependency which has not been declared an error is raised.
Required dependencies
dependency :vote_repo
When no default is specified the dependency must be injected via the constructor or setter an otherwise an exception will be raised.
Default dependencies
dependency :vote_repo, default: Vote
dependency :vote_repo, default: :vote
dependency :vote_repo, default: :Vote
dependency :vote_repo, default: 'Vote'
dependency :vote_repo, default: -> { Vote }
All the above examples will expose a method called vote_repo
which returns the
Vote
class as the default dependency.
Already got an initializer?
If you want to pass arguments other than the dependencies in to the constructor
don't forget to invoke super
:
def initialize(arg1, arg2, dependencies = {})
@arg1 = arg1
@arg2 = arg2
super(dependencies)
end
Compatibility
Tested with MRI 2.1+ and Rubinius.
See the build status for details.
Running Specs
rspec spec