No commit activity in last 3 years
No release in over 3 years
Interactor::Schema provides an enforcable Interactor Context
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

~> 1.13
~> 0.10
~> 10.0
~> 3.1

Runtime

 Project Readme

Interactor::Schema

Build Status

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.

Installation

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

Usage

See here for the official Interactor documentation.

Setup

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
end

Calling methods

When 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>

Use with Organizers

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
end

The 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.

Multiple Schemas

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.

Interactor Helper Methods

This gem comes with two helper methods - one that should help enforce context cleanliness and one to delegate to the context.

require_in_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
end

This will fail:

SaveUser.call
# => ArgumentError: Missing the following attributes in context: name

Whereas this will work:

SaveUser.call(name: "Bob")
# => #<Interactor::Context:0x007f9521298b10>

delegate_to_context

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
end

Development

After 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.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/berfarah/interactor-schema.

License

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