Skip to content

Interstate is a simple state machine which use interactors to trigger transitions

License

Notifications You must be signed in to change notification settings

SamuelMartini/interstate_machine

Repository files navigation

Maintainability Test Coverage

InterstateMachine

When state machine meets interactor. InterstateMachine is a simple state machine which use interactors to trigger transitions. Long story short, an object receives an event which is a interactor and you can do fantastic things with interactors. What is an interactor? "An interactor is a simple, single-purpose object."

Installation

gem install interstate_machine

Gemfile

gem 'interstate_machine', '~> 1.0.0'

Usage

class Order
  include InterstateMachine

  attr_accessor :state

  initial_state :cart

  transition_table :cart, :payment, :complete do
    on event: :next do |event|
      allow event: event, transition_to: [:payment], from: [:cart]
    end
    on event: :complete, transition_to: [:complete], from: [:payment]
  end
end

When including InterstateMachine in an ActiveRecord class, it does not need any attr_accessor to store the state. transition_table is where the state machine rules and states are defined. Each event represent an Interactor that is called to process the transition.

on can take a block which defines different transition(rules) for the same event or a single transition

In addition to the class where you define the state machine, you also need to create interactors for each event.

In this case we have an event next that could trigger many transitions(:cart, :address, :payment and so on) so we define an interactors for each of them. NextPayment, Complete. Yes, when an event triggers a transition to a single state and it's not a block, you have to name the class like the event name.

In a normal checkout you proably have something like NextAddress, NextDelivery, NextPayment, NextConfirm, Complete

class NextPayment
  include Interactor

  before :ensure_line_item

  def call
    # update order totals ..
  end

  private

  def ensure_line_item
    context.fail!(error: 'you need to add a product!') unless context.object.line_items.present?
  end
end

Note: You can use all the interactor magic (before, around, after) hooks. Whoop!

You can access the class where you have included InterstateMachine with context.object

When transition is allowed:

order = Order.new
order.add(line_item)
order.next
#=> :payment

When transition can't happen because something wrong executing the event

order = Order.new
order.next
#=> 'you need to add a product!'

When transition is no allowed

order = Order.new
order.state
#=> :cart
order.complete
#=> RuntimeError Exception:

Contributing

Feel free to play around, fork, add, pull request, and get a hug. If you decide to pull request please add tests

About

Interstate is a simple state machine which use interactors to trigger transitions

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages