# Make auto-register return classes instead of \`.new\` objects?

**URL:** <https://discourse.dry-rb.org/t/make-auto-register-return-classes-instead-of-new-objects/489>\
**Category:** Support\
**Created:** [February 26, 2018, 3:12am UTC](https://discourse.dry-rb.org/t/make-auto-register-return-classes-instead-of-new-objects/489 "2018-02-26T03:12:49Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![jonahx](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/jonahx/32/228_2.png) [@jonahx](https://discourse.dry-rb.org/u/jonahx)\
**Post date:** [February 26, 2018, 3:12am UTC](https://discourse.dry-rb.org/t/make-auto-register-return-classes-instead-of-new-objects/489/1 "2018-02-26T03:12:49Z")

</div>

I’ve got dry-system wired up, and it appears that by default auto-registered objects injected by `Import` are created by calling `new` on the class name, with no arguments. However, that is not always what I want.

There are two cases, in particular, that I have questions about.

1. The constructor of the injected class requires one or more arguments, and the arguments should be provided by the class into which it’s being injected. How is this case supposed to be handled? If we imagine a constructor with 2 arguments, the first of which is specified at runtime and contains the argument we need to pass to the constructor of the 2nd argument, then what we want is for the class itself to be injected as the 2nd argument, and then we would be able to `new` that class with the information from the first argument. There may be other solutions too…
2. I am injecting a module of pure static functions. That is, I want the module itself to be injected – I don’t want to call `new` on it.

Both of these cases would be simple enough to solve if I were configuring the container by hand user `register`. But what is the correct way to solve them while also using auto-register?

---

<div class="post-metadata">

**Author:** ![GustavoCaso](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/gustavocaso/32/86_2.png) [@GustavoCaso](https://discourse.dry-rb.org/u/GustavoCaso)\
**Post date:** [February 26, 2018, 10:18am UTC](https://discourse.dry-rb.org/t/make-auto-register-return-classes-instead-of-new-objects/489/2 "2018-02-26T10:18:32Z")

</div>

Hi, @jonahx.

Thanks for posting the question. I think an easy solution to this problem is to configure the `auto_registered`objects.

For the both scenario `class requires one or more arguments, and the arguments should be provided by the class into which it’s being injected` and `I want the module itself to be injected – I don’t want to call new on it` you could configure that all of the `auto_registered` would return the constant using the `auto_register!(path)` configure block:

```ruby
class Application < Dry::System::Container
  configure do |config|
    config.root = Pathname(File.dirname( __FILE__ )).parent
  end

  load_paths!('lib')
  auto_register!('lib') do |config|
    config.instance do |component|
      component.loader.constant
    end
  end
end

```

When passing a block to `auto_register!` method will yield a configuration object that responds to `instance` and `exclude` when calling any of the methods they will yield the component itself. The `instance` method is used in the register phase of the container

> <https://github.com/dry-rb/dry-system/blob/master/lib/dry/system/auto_registrar.rb#L38>

The exclude will be used for determining if a component should not be registered.

The `loader` part that you see it is used for loading the component

> <https://github.com/dry-rb/dry-system/blob/master/lib/dry/system/loader.rb#L62>

  
If all you component works this way, you could provide your custom loader to avoid having to use the `auto_register` configure block.

Hope this helps with your question, if you have more please do not hesitate to ask 😄

---

<div class="post-metadata">

**Author:** ![jonahx](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/jonahx/32/228_2.png) [@jonahx](https://discourse.dry-rb.org/u/jonahx)\
**Post date:** [February 27, 2018, 6:10am UTC](https://discourse.dry-rb.org/t/make-auto-register-return-classes-instead-of-new-objects/489/3 "2018-02-27T06:10:45Z")

</div>

@GustavoCaso,

Thanks for the reply. That worked!

Couple followup questions:

1. Where is this feature documented in the specs, if it is?

2. Note that because `auto_register!` takes only one argument, I had to call it multiple times in a loop – is there a better approach?

Jonah

```auto
require 'dry/system/container'

class Application < Dry::System::Container
  configure do |config|
    config.root = Pathname(File.dirname( __FILE__ )).parent
    config.auto_register = ['domain', 'lib', 'use_cases']
  end

  load_paths!('domain', 'lib', 'use_cases')
  ['domain', 'lib'].each do |dir|
    auto_register!(dir) do |config|
      config.instance do |component|
        component.loader.constant
      end
    end
  end
end

Application.finalize!

```

---

<div class="post-metadata">

**Author:** ![GustavoCaso](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/gustavocaso/32/86_2.png) [@GustavoCaso](https://discourse.dry-rb.org/u/GustavoCaso)\
**Post date:** [February 27, 2018, 8:31am UTC](https://discourse.dry-rb.org/t/make-auto-register-return-classes-instead-of-new-objects/489/4 "2018-02-27T08:31:43Z")

</div>

Hi @jonahx

Great glad that it works.

1. The specs for this are located here:

> <https://github.com/dry-rb/dry-system/blob/master/spec/unit/container/auto_register_spec.rb#L25>

1. Maybe we could make `auto_register!` to accept multiple `dir` like `config.auto_register`

BTW I think you do not have to `config.auto_register` and `auto_register!` twice the `domain` and `lib` folders in this case only in the `auto_register!` method because you need custom `auto_register` behavior.

---

<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:** [February 27, 2018, 9:44am UTC](https://discourse.dry-rb.org/t/make-auto-register-return-classes-instead-of-new-objects/489/5 "2018-02-27T09:44:12Z")

</div>

Returning constants defeats the purpose of having a container that resolves objects for you. The _whole point_ of using objects returned by a container is to decouple your code from details like object instantiation.

---

<div class="post-metadata">

**Author:** ![jonahx](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/jonahx/32/228_2.png) [@jonahx](https://discourse.dry-rb.org/u/jonahx)\
**Post date:** [February 27, 2018, 3:12pm UTC](https://discourse.dry-rb.org/t/make-auto-register-return-classes-instead-of-new-objects/489/6 "2018-02-27T15:12:19Z")

</div>

@solnic, Thanks. So what is the proper way to deal with the problems I raised in the OP? In particular, the question I raised in 1. in the OP?

EDIT:

To clarify my question above, I’m essentially confused by this:

1. On the one hand, we want the container to create all our objects for us, as you said.
2. The container’s `resolve` method takes only a key, so that it cannot instantiate objects whose constructors take arguments.
3. On the other hand, clearly some objects require arguments to construct.

Obviously I’m missing something quite simple here or else there is a miscommunication. Thanks for any clarifications.

---

<div class="post-metadata">

**Author:** ![timriley](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/timriley/32/25_2.png) [@timriley](https://discourse.dry-rb.org/u/timriley)\
**Post date:** [February 28, 2018, 1:31am UTC](https://discourse.dry-rb.org/t/make-auto-register-return-classes-instead-of-new-objects/489/7 "2018-02-28T01:31:11Z")

</div>

If your objects are legitimately abstract “services” or things that need to become dependencies of others, I’d suggest redesigning (or wrapping) them so they don’t accept this runtime data via their initializers, and instead via instance methods.

If for some reason they _must_ end up with the runtime data going into an object’s state, then you could follow the pattern of making it so the runtime options are _optional_ arguments to the initializer, and then you could supply a `#new` instance method that can accept the runtime args, merges them with any existing state, and returns a new instance with the merged args passed to `self.class.new`.

As for your second example, the module of static methods, since this is indeed static, and not something you’d ever want to be an abstract, substitutable service or dependency, there’s no need to use the container at all. Just require the file and refer to the concrete module name.

---

<div class="post-metadata">

**Author:** ![jonahx](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/jonahx/32/228_2.png) [@jonahx](https://discourse.dry-rb.org/u/jonahx)\
**Post date:** [February 28, 2018, 2:01am UTC](https://discourse.dry-rb.org/t/make-auto-register-return-classes-instead-of-new-objects/489/8 "2018-02-28T02:01:25Z")

</div>

> If your objects are legitimately abstract “services” or things that need to become dependencies of others, I’d suggest redesigning (or wrapping) them so they don’t accept this runtime data via their initializers, and instead via instance methods.

Yeah, that would be easy enough. I see that this is the pattern you’ve followed in the dry-transaction examples, and I’m doing something similar:

```auto
create_user = CreateUser.new
create_user.call("name" => "Jane", "email" => "jane@doe.com")

```

I think the way I was approaching this just wasn’t in harmony with the how the libraries work. I’m going to rework it and see if it improves.

> As for your second example, the module of static methods, since this is indeed static, and not something you’d ever want to be an abstract, substitutable service or dependency, there’s no need to use the container at all. Just require the file and refer to the concrete module name.

This is a good point. And probably it means that it _shouldn’t_ be static, even if they are library functions, because I might want to swap them out with some other implementation at some point.

---

<div class="post-metadata">

**Author:** ![jonahx](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/jonahx/32/228_2.png) [@jonahx](https://discourse.dry-rb.org/u/jonahx)\
**Post date:** [February 28, 2018, 1:39pm UTC](https://discourse.dry-rb.org/t/make-auto-register-return-classes-instead-of-new-objects/489/9 "2018-02-28T13:39:08Z")

</div>

@timriley,

One quick followup question after sleeping on this:

Since based on the above conversation, the best practice with container-created objects is for them to have 0 argument constructors, and accept arguments through a `call` method (or something similar) if they need to, the way the `CreateUser` example does, where do objects like `dry-struct` objects fit in?

Clearly their constructors take an argument… are they not candidates for container construction? And if not, what is different about them? Doesn’t an object that returns a `Dry::Struct`, for example, still have a dependency on it?

To take a similar example from inside `CreateUser` [here](http://dry-rb.org/gems/dry-transaction/basic-usage/):

```auto
def process(input)
    Success(name: input["name"], email: input["email"])
end

```

Here we clearly have a dependency on `Dry::Monad.Success`, but our dependency is hardcoded.

I’m not saying any of this is wrong or even that it looks odd to me… I’m just trying to understand the principle that determines which kinds of objects are appropriate for container injection and which are not.

Thanks.

---

<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:** [March 2, 2018, 10:10am UTC](https://discourse.dry-rb.org/t/make-auto-register-return-classes-instead-of-new-objects/489/10 "2018-03-02T10:10:56Z")

</div>

> I’m not saying any of this is wrong or even that it looks odd to me… I’m just trying to understand the principle that determines which kinds of objects are appropriate for container injection and which are not.

DI should be used **for object composition exclusively**. You will never compose objects from things like data structures or result objects. It’s good to think about these as types. Every specific data structure is a specific type, same with result objects, you have success and failure types. It’s also the reason why I suggested assigning data schemas from dry-v to constants, and treating them as types, in a similar way we have types from dry-types.

We gotta document this properly somewhere…

---

<div class="post-metadata">

**Author:** ![jonahx](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/jonahx/32/228_2.png) [@jonahx](https://discourse.dry-rb.org/u/jonahx)\
**Post date:** [March 2, 2018, 1:13pm UTC](https://discourse.dry-rb.org/t/make-auto-register-return-classes-instead-of-new-objects/489/11 "2018-03-02T13:13:24Z")

</div>

@solnic,

Thanks for the explanation. That makes sense.

To be sure I have it right, would it be accurate to say:

1. It’s ok to have “hardcoded” dependency to “types.” For example, inside a repo it’s okay to have code like `return SomeDomainObject.new(blah, blah, blah)` because `SomeDomainObject` here is essentially just a type. We don’t inject these objects.
2. If you have an object that _performs computation_ – whether that be db inserts, validation, or some complex mathematical calculation – then that object should be injected, if it’s being used by another object.

Let me know if I’m still mistaken in some way, or if you’d adjust the way I phrased that.

---

<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:** [March 2, 2018, 1:54pm UTC](https://discourse.dry-rb.org/t/make-auto-register-return-classes-instead-of-new-objects/489/12 "2018-03-02T13:54:28Z")

</div>

> [@jonahx](#):
>
> Let me know if I’m still mistaken in some way, or if you’d adjust the way I phrased that.

This sounds correct 🙂

---

<div class="post-metadata">

**Author:** ![bsielski](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/bsielski/32/359_2.png) [@bsielski](https://discourse.dry-rb.org/u/bsielski)\
**Post date:** [March 23, 2019, 9:17am UTC](https://discourse.dry-rb.org/t/make-auto-register-return-classes-instead-of-new-objects/489/13 "2019-03-23T09:17:11Z")

</div>

> [@jonahx](#):
>
> I’ve got dry-system wired up, and it appears that by default auto-registered objects injected by `Import` are created by calling `new` on the class name, with no arguments. However, that is not always what I want.

It looks like it can be achieved by injecting a **module** with `self.new` method. The injector will call `new` method on the module like it was a class.
