# Dry-AutoInject with Dry-Initializer, order matters

**URL:** <https://discourse.dry-rb.org/t/dry-autoinject-with-dry-initializer-order-matters/379>\
**Category:** Support\
**Created:** [October 25, 2017, 9:45pm UTC](https://discourse.dry-rb.org/t/dry-autoinject-with-dry-initializer-order-matters/379 "2017-10-25T21:45:54Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![kbacha](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/kbacha/32/107_2.png) [@kbacha](https://discourse.dry-rb.org/u/kbacha)\
**Post date:** [October 25, 2017, 9:45pm UTC](https://discourse.dry-rb.org/t/dry-autoinject-with-dry-initializer-order-matters/379/1 "2017-10-25T21:45:54Z")

</div>

I was working with Dry-Initializer and with Dry-AutoInject and noticed that my injected dependency wasn’t getting populated. The field was there but the value was not. After some digging I discovered that the order that the injected dependency is loaded matters:

```ruby
require 'dry_auto_inject_issue/version'
require 'dry-auto_inject'
require 'dry-container'
require 'dry-initializer'

module DryAutoInjectIssue
  class Container
    extend Dry::Container::Mixin

    register 'test' do
      'some string'
    end
  end

  Import = Dry::AutoInject(Container)

  class BrokenlyInjected
    include Import['test']
    extend Dry::Initializer

    param :arg1
  end

  class Injected
    extend Dry::Initializer
    include Import['test']

    param :arg1
  end

  class Workaround
    extend Dry::Initializer

    param :arg1
    option :test, default: -> { Container.resolve('test') }
  end
end

```

```ruby
$ bin/console
2.4.2 :001 > DryAutoInjectIssue::BrokenlyInjected.new('hello').test
 => nil
2.4.2 :002 > DryAutoInjectIssue::Injected.new('hello').test
 => "some string"
2.4.2 :003 > DryAutoInjectIssue::Workaround.new('hello').test
 => "some string"
2.4.2 :004 >

```

I’m not sure if this is something that is known or should be fixed. But it was an interesting and unexpected behavior when using the system.

---

<div class="post-metadata">

**Author:** ![solnic](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/solnic/32/779_2.png) [@solnic](https://discourse.dry-rb.org/u/solnic)\
**Post date:** [October 26, 2017, 7:32am UTC](https://discourse.dry-rb.org/t/dry-autoinject-with-dry-initializer-order-matters/379/2 "2017-10-26T07:32:26Z")

</div>

Why do you need both dry-initializer AND dry-auto\_inject, both provide constructors, so I’d recommend using one or the other, not both. In applications we don’t use dry-initializer at all, for me it’s a low-level lib (of course I understand that it could be used differently, as it’s quite flexible).

---

<div class="post-metadata">

**Author:** ![kbacha](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/kbacha/32/107_2.png) [@kbacha](https://discourse.dry-rb.org/u/kbacha)\
**Post date:** [October 26, 2017, 8:38pm UTC](https://discourse.dry-rb.org/t/dry-autoinject-with-dry-initializer-order-matters/379/3 "2017-10-26T20:38:16Z")

</div>

I ended up not using both as it wasn’t working as expected and modification could easily break it’s functionality (opting for the `Workaround` class above).

For this specific case, I was toying with how to inject a Logger into small classes without needing to pass it around via args. The logging level was being controlled via a CLI but it was cumbersome (and not really the correct interface) to pass the logger reference around. However, other aspects of the constructor were not able to be implicitly injected so I was using initializer.

I honestly really enjoy using initializer for just about every class I create that does more than just hold data. If it just holds data I use a `Dry::Struct::Value` but in much of my work I create Functions as an Object and using the initializer to define the signature gives me control/safety around how the caller uses it. It also provides a really nice declarative interface with typings, defaults, and coercions that a normal method signature does not.

As for my specific use-case, a singleton is all I really needed. I wanted to see if dependency injection would solve my case because it’s a littler more explicit in terms of declaring the requirements for a class. It also shortens the call signature to a method on the callee. This means when logging I use `self.logger` vs `TopLevelModule.logger`. Another solution might have been a mixin to inject the `logger` method `include TopLevelModule::Logger` but that adds to the ancestor tree of a my class making it a “logger” when it’s not really. I personally spend a lot of times thinking about what each of my classes “are” and this seemed to violate that.

Perhaps there’s another solution to my problem that I haven’t considered. However, the ordering issue here was still slightly unexpected.

---

<div class="post-metadata">

**Author:** ![solnic](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/solnic/32/779_2.png) [@solnic](https://discourse.dry-rb.org/u/solnic)\
**Post date:** [October 28, 2017, 4:01pm UTC](https://discourse.dry-rb.org/t/dry-autoinject-with-dry-initializer-order-matters/379/4 "2017-10-28T16:01:03Z")

</div>

If you have objects that hold data, then using DI is rather weird. DI is useful in objects that act as “services”, as in, they do something _with_ objects that hold data. Mixing constructors that set data and accept external dependencies is not something that I’d recommend.

---

<div class="post-metadata">

**Author:** ![kbacha](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/kbacha/32/107_2.png) [@kbacha](https://discourse.dry-rb.org/u/kbacha)\
**Post date:** [October 28, 2017, 11:08pm UTC](https://discourse.dry-rb.org/t/dry-autoinject-with-dry-initializer-order-matters/379/5 "2017-10-28T23:08:04Z")

</div>

I think you misunderstood me since it feels like you repeated what I was saying. If an object holds data I use `Dry::Struct::Value`. What you describe as a “service” object I think of as a “Function as an Object”. When I said

> does more than just hold data

I meant to imply that every object holds some amount of data but if it has verbs attached to it (such as `perform` or `run` or `compute`) then I switch to the more semantic `Dry::Initializer`.

---

<div class="post-metadata">

**Author:** ![kbacha](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/kbacha/32/107_2.png) [@kbacha](https://discourse.dry-rb.org/u/kbacha)\
**Post date:** [October 28, 2017, 11:35pm UTC](https://discourse.dry-rb.org/t/dry-autoinject-with-dry-initializer-order-matters/379/6 "2017-10-28T23:35:14Z")

</div>

As for the need to have required constructor params, it seems likely that not everything about what a “service” object needs can be injected, somethings may have runtime requirements and need to be passed in. I suppose in these cases it might make sense to make them arguments to the function on the service object:

```ruby
class Test
  include Imports['dependency']

  def perform(arg1)
    sub_action(arg1)
  end

  private

  def sub_action(arg1)
  end
end

```

This is currently missing a clean declarative dry format. So I prefer to have them as part of the initializer right now. As a bonus the initializer makes them available without needing to do argument passing. If `arg1` is a function argument I need to pass it to all subsequent method calls. With a single argument, this isn’t too bad, but for 2 or 3 it gets a lot less dry. When it’s initialized then it’s available within the object scope and is a lot cleaner:

```ruby
class Test
  extend Dry::Initializer
  include Imports['dependency']

  param :arg1

  def perform
    sub_action
  end

  private

  def sub_action
    # do something with arg1
  end
end

```

I also get the value of self documenting code if that param can be defaulted or has a type. This is useful for some changes in behavior that aren’t connected to external dependencies. Or are essentially arguments on data to read/transform. In my usecase, it was creating a service object that took a file path and parsed the yaml data. The path is checked for format as a `Dry::Types` (named `Types::Path` in this case).

```ruby
class Loader
  extend Dry::Initializer

  param :filepath, Types::Path

  def load!
    # Do something with the filepath
  end
end

```

But since this was connected with a CLI I was trying to wire up a logger to expose debug steps during it’s flow.

I ended up not using auto inject in this case but I am using a container to expose a singleton logger that can be referenced from other places. This was a dependency that I wanted injected but the service object still had arguments that it needed at run time (ie, cannot be injected). I may switch the logger to be a simple singleton using Ruby but I found the method signature to be wonky: `MyNamespace.logger.debug { 'log message' }`. By using autoinject, i was hoping for a cleaner call: `logger.debug { 'log message' }`. I may stop using containers for this as well as a Ruby Singleton as the default to an initializer generally saves the same problem.
