How does it work?

dry-auto_inject enables constructor dependency injection for your objects. It achieves this by defining two methods in the module that you include in your class.

First, it defines .new, which resolves your dependencies from the container, if you haven’t otherwise provided them as expicit arguments. It then passes these dependencies as arguments onto #initialize, as per Ruby’s usual behaviour.

It also defines #initialize, which receives these dependencies as arguments and then assigns them to instance variables. These variables are made available via attr_readers.

So when you specify dependencies like this:

Import = Dry::AutoInject(MyContainer)

class MyClass
  include Import["users_repository"]

You’re building something like this (this isn’t a line-for-line copy of what is mixed into your class; it’s intended as a guide only):

class MyClass
  attr_reader :users_repository

  def self.new(**args)
    deps = {
      users_repository: args[:users_repository] || MyContainer["users_repository"]


  def initialize(users_repository: nil)

    @users_repository = users_repository

Since these methods are defined in the module that you include in your class, you can still override them in your class if you wish to provide custom behavior.