Dependencies Hanami: 1.x

Dry Container + AutoInject

/config/autoinject.rb

class Container
  extend Dry::Container::Mixin

  register('webpack_manifest', memoize: true) do
    ::WebpackManifest.new('public/assets.json')
  end

  register('cache', memoize: true) do
    Readthis::Cache.new(
      expires_in: 86400,
      redis: {
        url: ENV['REDIS_URL'],
        driver: :hiredis
      }
    )
  end
end

AutoInject = Dry::AutoInject(Container)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

/config/environment.rb





 


require 'bundler/setup'
require 'hanami/setup'
require 'hanami/model'
#...
require_relative './autoinject'
#...
1
2
3
4
5
6

after that you can access registered instance via

Container[:webpack_manifest]
# call methods etc.
Container[:webpack_manifest].resolve_entry(script)
1
2
3

Stub component in Tests

Imagine you have PubNub WebSockets dependency registered.

/config/autoinject.rb

class Container
  extend Dry::Container::Mixin

#...
  register('pubnub') do
    pubnub_params = {
      subscribe_key: ENV['PUBNUB_SUBSCRIBE_KEY'],
      publish_key: ENV['PUBNUB_PUBLISH_KEY'],
      secret_key: ENV['PUBNUB_SECRET_KEY'],
      ssl: true
    }
    Pubnub.new(pubnub_params)
  end
#...

end

AutoInject = Dry::AutoInject(Container)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

And your code is sending PubNub messages allover the app. We definitely do not want to pay crazy bills for sending tons of messages during test runs. Yeees, maybe your architecture could be a little bit better to have an ability to turn these messages off during tests. But you could even want to make assertions on how much and what messages are being sent.

Add such line in tests configuration


 

AutoInject.container.enable_stubs!
AutoInject.container.stub('pubnub', PubnubClientStub.new)
1
2

and implement your Stub class, for example as simple as that.

/spec/support/pubnub_client_stub.rb

class PubnubClientStub
  attr_accessor :messages

  def initialize
    @messages = []
  end

  def publish(payload)
    @messages.push(payload)
  end
end
1
2
3
4
5
6
7
8
9
10
11

This assumes that publish is the only public method used. You need to implement all public API of stubbed class.

Hanami Container usage

// TODO

Dry System autoloading

https://github.com/davydovanton/dry-system-hanami

require 'dry/system/container'
require 'dry/system/hanami'

class Container < Dry::System::Container
  extend Dry::System::Hanami::Resolver

  register_folder! 'project_name/repositories'
  # or with custom resolver
  register_folder! 'project_name/matchers', resolver: ->(k) { k }

  configure
end
1
2
3
4
5
6
7
8
9
10
11
12