No commit activity in last 3 years
No release in over 3 years
A guided interactor
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Development

~> 1.17
~> 10.0
~> 3.0
 Project Readme

Guided Interactor

Guided Interactor is a spin-off from the interactor gem. The Interactor Design Pattern allows us to build simple, single-purpose objects that move the business logic away from controllers and models. However, it also has some downsides, with the biggest pain point for me being the "Black Box Effect" with context - you never know what goes in or what comes out.

# Typical interactor:

class Foo
  include Interactor

  def call
    context.message = "#{context.greeting} #{context.name.capitalize}!"
  end
end

Foo.call(greeting: "Hello", name: "Waldo")
=> #<Interactor::Context greeting="Hello", name="Waldo", message="Hello Waldo!">

Foo.call(greeting: "Hi")
NoMethodError: undefined method `capitalize' for nil:NilClass

Guided Interactor is trying to fill the gap by providing more flexibility and clarity. Previously we have agreed to use delegate :foo, to: :context on two separate lines to define parameters expected and parameters that are set inside the interactor. This gem introduces 3 additional methods: expects, expects! and provides:

class MyInteractor
  include GuidedInteractor

  expects :foo
  expects! :bar
  provides :waldo
  
  def call
    # do smth
  end

end

expects and provides are aliases and simply delegate the specified parameters to the context. expexts! does the same, but adds a before hook that fails the context if any of the parameters is missing. The example above could then be rewritten like this:

# Guided interactor:

class Foo
  include GuidedInteractor
  
  expects :greeting
  expects! :first_name, :last_name
  provides :message

  def call
    context.message = "#{greeting} #{first_name.capitalize} #{last_name.capitalize}!"
    puts message
  end
end

Foo.call(greeting: "Hello", first_name: "Waldo", last_name: "smith")
Hello Waldo Smith!
=> #<GuidedInteractor::Context greeting="Hello", first_name="Waldo", last_name="smith", message="Hello Waldo Smith!">

result = Foo.call(greeting: "Hi")
=> #<GuidedInteractor::Context greeting="Hi">
result.success?
=> false

Foo.call!(greeting: "Hi", first_name: 'John')
GuidedInteractor::Failure: #<GuidedInteractor::Context greeting="Hi", first_name="John">

Future plans

In the future, there are plans to add further guidance to guided interactors, including more validations, defaults and error handling.

License

The gem is available as open source under the terms of the MIT License.