Make interactor closer to action by adding params validation?



I have been fascinated with lotus for the last two weeks. Thanks for the amazing job. I came to it finding about more robust application architectures after a Rails app was growing out of control. I found about trailblazer operations and when coming to Lotus the controller is extremely similar. It however is coupled to HTTP. Then I learnt about the interactor and going through the current source code I understood how to use it to structure business logic than I can use both in controllers (for HTTP) and in other things, like sidekiq workers.

I noticed that the interactor doesn’t have params validation on it’s own, so I found myself doing something like this:

module Api::Interactions
  class Detokenization

    class Params
      include Lotus::Validations
      attribute :public_token, presence: true

    include Lotus::Interactor

    def initialize(params)
      @params = params

    def call
      # only invoked if validations pass


    def detokenize(token)

    def valid?
      if @params.valid?       
        return true # this is required!
        @errors = @params.errors
        error! "Bad parameters"


Since the logic should guard for correct input the inclusion of a Params class mimmicks what’s currently done in the Controller. So I wanted to propose the following:

  • Make the Interactor have a self.params just like controllers.
  • Specify a desired way to route params errors. (maybe it’s just a readme example?)

I understand that the current architecture uses modules and separate gems as optional dependencies. The validations gem is not in the utils code so maybe the whole problem could be tackled with a validations module that can be included in addition to Interactor to have the desired effect?

Finally, I’m not entirely sured that the interactions should be handled through the call method on the instance, this has the strange option of allowing the op to be called twice. Alternatively having class methods could be nice. This is how trailblazer does it and makes everything focus on the params passed to the method on the class and remove the initialization process that could make it more complex to precisely understand the parts involved. Maybe a matter of taste but I’m still leaving the comment here to see what you think.