IIInteractor
A base interactor to support management of bussiness logic.
This gem is inspired by interactor specs.
Dependencies
- ruby 2.3+
- activesupport 5.0+
Installation
Add this line to your application's Gemfile:
gem 'ii_interactor'
Then execute:
$ bundle
Usage
Create interactor with call
method and call it as follows:
class Interactor < IIInteractor::Base
context :message
context :result
def call
@context.result = "called by #{@context.}"
end
end
Interactor.call(message: 'something')
#=> #<IIInteractor::Context @_data={:message=>"something", :result=>"called by something"}>
The first argument of Interactor.call
is set to @context
.
The return value of Interactor.call
is the same as @context
.
You can define context variables used in interactor explicitly by using the context
method.
context
method copies the input variables to instance variables of the interactor.
Context options
You can define required context as follows:
class Interactor < IIInteractor::Base
context :input, required: true
end
Interactor.call
#=> missing required context: input (Coactive::MissingContextError)
You can also define default value as follows:
class Interactor < IIInteractor::Base
context :input, default: 'input'
def call
puts @input
end
end
Interactor.call
#=> input
You can also set context from return value of call
method:
class Interactor < IIInteractor::Base
context :result, output: :return
def call
'returned value'
end
end
Interactor.call.result
#=> returned value
Coactions
You can call other interactors in the same context using coact
:
class AInteractor < IIInteractor::Base
def call
puts self.class.name
end
end
class BInteractor < IIInteractor::Base
def call
puts self.class.name
end
end
class MainInteractor < IIInteractor::Base
coact AInteractor
coact BInteractor
end
MainInteractor.call
#=> AInteractor
# BInteractor
See coactive for more coact
examples:
Stop interactions
You can stop interactions as follows:
class AInteractor < IIInteractor::Base
def call
puts self.class.name
stop!(message: "something happened!")
end
end
class BInteractor < IIInteractor::Base
def call
puts self.class.name
end
end
class MainInteractor < IIInteractor::Base
coact AInteractor
coact BInteractor
context :message
end
context = MainInteractor.call
#=> AInteractor
context.
#=> something happened!
context.stopped?
#=> true
context.success?
#=> true
Fail interactions
You can fail interactions and rollback called interactors as follows:
class AInteractor < IIInteractor::Base
def call
puts self.class.name
end
def rollback
puts "rollback #{self.class.name}"
end
end
class BInteractor < IIInteractor::Base
def call
fail!(message: "something happened!")
end
def rollback
puts "rollback #{self.class.name}"
end
end
class MainInteractor < IIInteractor::Base
coact AInteractor
coact BInteractor
context :message
end
context = MainInteractor.call
#=> AInteractor
# rollback AInteractor
context.
#=> something happened!
context.failure?
#=> true
Callbacks
Following callbacks are available:
before_all
,around_all
,after_all
before_call
,around_call
,after_call
*_all
wraps all coactors, and *_call
wraps call
method.
That is, before_all
is called before running all coactors, and before_call
is called before running call
method.
For example:
class Interactor < IIInteractor::Base
context :message
before_all do
puts "before_all"
end
before_call do
puts "before_call"
end
def call
puts @context.
end
end
Interactor.call(message: 'something')
#=> before_all
# before_call
# something
Pass a block
You can pass a block to call
method of a interactor.
The block is kept in the context and you can call it by inform
as you like:
class AInteractor < IIInteractor::Base
def call
inform('called A')
end
end
class BInteractor < IIInteractor::Base
def call
inform('called B')
end
end
class MainInteractor < IIInteractor::Base
coact AInteractor
coact BInteractor
end
MainInteractor.call do |interactor, |
puts "#{interactor.class}: #{}"
end
#=> AInteractor: called A
# BInteractor: called B
Logging
Interactor supports instrumentation hook supplied by ActiveSupport::Notifications
.
You can enable log subscriber as follows:
IIInteractor::LogSubscriber.attach_to :ii_interactor
This subscriber will write logs in debug mode as the following example:
Calling BasicInteractor with #<IIInteractor::Context ...>
...
Called BasicInteractor (Duration: 0.1ms, Allocations: 4)
Contributing
Bug reports and pull requests are welcome at https://github.com/kanety/ii_interactor.
License
The gem is available as open source under the terms of the MIT License.