Skip to content

Dependency Injection

Vladimir Kalinkin edited this page Jun 4, 2018 · 5 revisions

Basics

Dependency Injection (DI) is a heart of Dandy web-application. Every Dandy action can utilize known variables/entities in the application. In example:

when you have:

    GET /auth/posts/$id (show_post)

you can easily use request parameter:

class ShowPost
  def initialize(id)
    @id = id
  end
  
  def call
    # somehow extract a post using @id
  end
end

Every action returns a result that automatically registers in the container and can be used in further actions:

    GET     /auth/posts/$id (load_post, show_post)
class ShowPost
  def initialize(load_post_result)
    @post = load_post_result
  end
  # ...
end

It's better to use exact name of returned result in the routing definition: /post/$id -> GET -> post@load_post -> show_post

and use it:

class ShowPost
  def initialize(post)
    @post = post
  end
  
  # ...
end

In order to support another types by DI you need to adjust the configuration dandy.yml:

path:
  dependencies:
    - actions # default location
    - services/injectable # additional dependencies location

Objects Lifetime

As mentioned before, dependency injection is a heart of Dandy. And as you probably noticed we register dependencies for every new request. In order to avoid leaking the memory for request-specific objects Dandy uses Hypo::Scope lifetime style for registered objects. Every time when request is ending the dependencies remove from the container.

BTW, using Hypo::Scope and it's finalize method definition you can implement Unit of Work pattern.

class DbSession
  include Hypo::Scope
  
  def initialize
    @transaction = Transaction.new
  end

  def finalize
    # unexpected behavior handling is in :catch section implementation
    @transaction.commit      
  end
end

Clone this wiki locally