dry-transaction isn’t designed out of the box to automatically handle injection of arbitrary dependencies — it’s designed to help you compose multiple operations to run as steps in a sequence, and it will help you inject those objects.
e.g.
class MyTransaction
step :one_thing
step :another_thing
end
# inject operation object for "one_thing" step
my_trans = MyTransaction.new(one_thing: -> input { do_something })
my_trans.("input")
Now, injecting other things into a transaction object is a different matter. I’ve never tried it myself, which is why I couldn’t give you a quick answer to your questions.
I’ve just looked into it now, and it seems like it’s now possible with the initialize that dry-transaction provides. I’m going to file a couple of issues for this, since it’s something that I would like to make possible, eventually.
Sorry this doesn’t help you in the short term, though.
May I make one suggestion, though? I don’t think you need a transaction in this case. I certainly wouldn’t use one for an object like the one you shared. I think it’s perfectly fine to build up that kind of logic by hand, for example:
require "dry-auto_inject"
require "dry-monads"
Import = Dry::AutoInject(MyContainer)
class CreateArticle
# dry-auto_inject can take care of importing this for you
include Import[article_repo: "repositories.articles"]
include Dry::Monads::Result::Mixin
def call(input)
validation = ArticleSchema.(input)
if validation.success?
article = article_repo.create(validation.to_h)
Success(article)
else
Failure(validation.errors)
end
end
end
This is exactly like how I build up standard CRUD operation objects in the apps I build. I think it’s more obvious than the transaction approach and will more easily support adding in nuanced operation-specific behaviour in future.