Dinja, Dependency Injection Ninja
Add this line to your application's Gemfile:
gem "dinja"
And then execute:
$ bundle install
Or install it yourself as:
$ gem install dinja
# Instantiate a dependency injection container
container = Dinja::Container.new
# Register a dependency
container.register("my_dependency") { |name| OpenStruct.new(name: name) }
# Resolve a dependency
my_dependency = container.resolve("my_dependency", "foobar")
puts my_dependency.name
# => "foobar"
# Look up a dependency (without resolving)
my_dependency = container.lookup("my_dependency")
puts my_dependency.call("foobar")
# => #<OpenStruct name="foobar">
# Container#resolve will raise when trying to resolve unregistered dependencies
# Use Container#resolve! to resolve unregistered dependencies without raising (dangerous)
container.resolve("another_dependency")
# => DependencyNotRegistered
# Container#lookup will raise when trying to look up unregistered dependencies
# Use Container#lookup! to look up unregistered dependencies without raising (dangerous)
container.lookup("another_dependency")
# => DependencyNotRegistered
# Container#register will raise when trying to overwrite registered dependencies
# Use Container#register! to overwrite dependencies (dangerous)
container.register("my_dependency") { |name| OpenStruct.new(name: name) }
In a Rails application, add the following line to your config/application.rb
:
require "dinja/railtie"
Create config/dependencies.rb
and register some dependencies:
register("my_dependency") do |name|
OpenStruct.new(name: name)
end
A dependency injection container is now available throughout your application on Rails.application.config.container
:
my_dependency = Rails.application.config.container.resolve("my_dependency", "foobar")
my_dependency.name
# => "foobar"
In a gem, add the following lines to your lib/my_gem.rb
:
require "dinja"
module MyGem
def container
@container ||= Dinja::Container.new
end
def setup
# ...other stuff here
# Register dependencies
container.instance_eval(File.read("config/dependencies.rb"))
end
end
MyGem.setup
Create config/dependencies.rb
and register some dependencies:
register("my_dependency") do |name|
OpenStruct.new(name: name)
end
A dependency injection container is now available throughout your application on MyGem.container
:
my_dependency = MyGem.container.resolve("my_dependency", "foobar")
my_dependency.name
# => "foobar"
If you need to mock resolution calls to a container, you can do as following.
In spec/support/dinja.rb
:
require "dinja/rspec"
RSpec.configure do |config|
config.include Dinja::RSpec
end
In config/dependencies.rb
:
register("my_service") do |name|
OpenStruct.new(name: name)
end
In spec/my_app/my_model_spec.rb
:
RSpec.describe MyApp::MyModel do
subject(:my_model) { described_class.new }
it "calls my service" do
my_service = dinja_mock!("my_service")
allow(my_service)
.to receive(:call)
.and_return true
my_model.call_service
expect(my_service).to have_received(:call)
end
end
To release a new version, update the version number in lib/dinja/version.rb
, update the changelog, commit the files and create a git tag starting with v
, and push it to the repository.
Github Actions will automatically run the test suite, build the .gem
file and push it to rubygems.org.
Bug reports and pull requests are welcome on GitHub at https://github.com/floriandejonckheere/dinja.
The gem is available as open source under the terms of the MIT License.