Interactor::Schema provides an enforcable Interactor Context via a schema
class method.
This gem was born out of frustration. In using Interactor, I often wouldn't know
what methods would be defined on it. By forcing a schema upfront, and also
requiring methods in Interactor classes, we bring order to
Interactor::Context.
Put this in your application's Gemfile:
gem 'interactor'
gem 'interactor-schema'And then execute:
$ bundle
Or install it yourself as:
$ gem install interactor-schema
See here for the official Interactor documentation.
When you include Interactor::Schema, you are able to define a schema for valid
context methods using the schema DSL method.
class SaveUser
include Interactor::Schema
schema :name
endWhen the attribute is part of the valid schema, you will have no problems accessing it as usual:
context = SaveUser.call(name: "Bob")
context.name
# => "Bob"For attributes outside the schema, you will get NoMethodErrors. The same thing
applies when trying to set an attribute outside of the schema.
context = SaveUser.call(age: 28)
context.age
# NoMethodError: undefined method 'age' for #<SaveUser:0x007f9521298b10>Interactor::Schema works great with Interactor::Organizers!
class SaveUser
include Interactor::Schema
include Interactor::Organizer
schema :name
organize ValidateInfo, SendMailer
end
class ValidateInfo
include Interactor
def call
# These will work, since name is in our schema
context.name
context.name = "Bob"
# These will fail with NoMethodErrors since age is not in our schema
context.age
context.age = 28
end
endThe initial schema will be propagated through the entire chain, meaning no
attributes outside of name can be set. This is particularly helpful for
maintaining clarity of what information is being consumed by a chain of
Interactors.
In the case of multiple schemas being provided only the first one will be used (others will be discarded). The idea is that you should know upfront what attributes will be needed.
Modifying the schema in the middle of the chain could result in confusing behavior.
This gem comes with two helper methods - one that should help enforce context cleanliness and one to delegate to the context.
Interactor::require_in_context ensures that the attributes provided as
arguments are present and not nil? when the service is called.
class SaveUser
include Interactor
require_in_context :name
endThis will fail:
SaveUser.call
# => ArgumentError: Missing the following attributes in context: nameWhereas this will work:
SaveUser.call(name: "Bob")
# => #<Interactor::Context:0x007f9521298b10>Interactor::delegate_to_context creates a method that delegates to the
context.
class SaveUser
include Interactor
delegate_to_context :name
# is equivalent to:
def name
context.name
end
endAfter checking out the repo, run bin/setup to install dependencies. Then, run rake test to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.
Bug reports and pull requests are welcome on GitHub at https://github.com/berfarah/interactor-schema.
The gem is available as open source under the terms of the MIT License.