0.0
No release in over 3 years
Automatic Dependency Injection where you get to see and keep control of the constructor
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Runtime

 Project Readme

Gem version GitHub repo Codeberg repo

LowDependency

Automatic Dependency Injection where you get to see and keep control of the constructor.

Injection

Inject a dependency:

class MyClass
  include LowType

  def initialize(my_dependency: Dependency)
    @my_dependency = my_dependency # => "my_dependency" is injected.
  end
end

ℹ️ The 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 # => "@my_dependency" is injected.
  end
end

This method hides and creates the constructor on your behalf.

Providers

Provide the dependency with:

LowDependency.provide(:my_dependency) do
  MyDependency.new
end

Namespaced string keys are fine too:

LowDependency.provide('billing.payment_provider') do
  PaymentProvider.new
end

Mixing dependency types

LowDependency lets you do something special; mix "classical" dependency injection (passing an arg to new) with "provider" style dependency injection (populating an arg via a framework):

LowDependency.provide(:provider_dependency) do
  ProviderDependency.new
end

# Define both a "provider" and a "classical" dependency:
class MyClass
  include LowType

  def initialize(provider_dependency: Dependency, classical_dependency:)
    @provider_dependency = provider_dependency
    @classical_dependency = classical_dependency
  end
end

# Now bring it all together by calling:
MyClass.new(classical_dependency: ClassicalDependency.new)

The provider_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 🥣

API

Dependency Expression

A Dependency Expression defines the dependency to be injected, the provider that will inject it and the name of the local variable that it will be made available as.

The def(dependency: Dependency) syntax is an Expression; an object composed via a query builder like interface. It follows the same logically consistent rules as other expressions in the Expressions API.

To define a provider with a different name to that of the local variable do:

def initialize(dependency_one: Dependency | :provider_one)
  dependency_one # => Dependency injected from :provider_one.
end

For providers with string keys do:

def initialize(dependency_two: Dependency | 'billing.provider_two')
  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.

Traditional Dependency

The include style syntax supports the same functionallity as the dependency expression syntax.

Multiple dependencies:

class MyClass
  include LowDependency[:dependency_one, :dependency_two]
end

Dependencies 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.
end

ℹ️ Provider keys with a namespace such as 'billing.provider_two' will have their dependency injected without the namespace; the variable will just be @provider_two.

Separating 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,
  ]
end

Installation

Add gem 'low_dependency' to your Gemfile then:

bundle install