I think this might come down to a misunderstanding of the call:
option for register
, and what exactly the registered item is in your examples.
Let’s take this registration of yours as a starting point:
register(:connection, call: true) { Connection.new }
It might be helpful to restructure it a little to make it clear just what the registered item will be in this case:
register(:connection, call: true, Proc.new { Connection.new })
The registered item in this case is actually this Proc object, which is what dry-container will turn a provided block into behind the scenes. (Reminder: dry-container is what dry-system uses under the hood).
From here, what call: true
tells dry-container to do is to call that registered proc whenever you resolve your registered component. And in your example, calling Proc.new { Connection.new }
will return a new instance of your Connection
.
In fact, any time you provide a block (or indeed a Proc object) to register
, dry-container will set call: true
for you automatically, so these are both equivalent to the examples above:
# Both equivalent, since `call: true` is set for all registered Procs
register(:connection) { Connection.new }
register(:connection, Proc.new { Connection.new })
Now to help understand this completely, if we inverted the call:
option and set it to false, here’s what would happen:
MyContainer.register(:connection, call: false) { Connection.new }
MyContainer.resolve(:connection) # => Supplied Proc instance, e.g. #<Proc:0x00000001120786c8>
MyContainer.resolve(:connection).call # => A Connection instance, e.g. #<Connection:0x000000011210e4c0>
What this all should hopefully show is that when you’re registering items with a block, what call: true
means (and why its set to true by default for blocks) is that it will call the block’s proc itself to return whatever you’re returning from the block. What it won’t do is send #call
to that object. This is your job to do as the user of the container, once you have resolved that object.
So from here I’d recommend you take one of two options:
- Register your connection with the block like you’ve been currently doing, and make an extra step within your application code to
.call
that Connection
object once you’ve resolved it from the container
- Or initialize that
Connection
eagerly somewhere, and then send .call
it and register that resulting object directly on the container
There might actually be other options here, but it’s a bit hard for me to guess at that without knowing a bit more about your circumstances. If you could share more, I’d be happy to offer more suggestions!
Either way, hopefully this helps clear things up a little about how dry-container callable registrations work