Sha256: 4c201bc428be621baa3b2938770348123bdfabd8fe4b10e71dc2cfdccff06093

Contents?: true

Size: 1.51 KB

Versions: 3

Compression:

Stored size: 1.51 KB

Contents

# frozen_string_literal: true

class MicroFSM
  InvalidEvent = Class.new(NoMethodError)
  InvalidState = Class.new(ArgumentError)
  InvalidTransition = Class.new(ArgumentError)

  attr_reader :state

  def initialize(initial_state)
    @state = initial_state
    @transitions_for = {}
    @callbacks_for = {}
  end

  def when(event, transitions, &block)
    @transitions_for[event] ||= {}
    @callbacks_for[event] ||= {}

    transitions.each do |from, to|
      nto = @transitions_for[event][from]
      raise InvalidTransition if nto && nto != to

      @transitions_for[event][from] = to
      @callbacks_for[event][from] ||= []
      @callbacks_for[event][from] << block if block_given?
    end
    self
  end

  def trigger(event)
    trigger?(event) and transit(event)
  end

  def trigger!(event)
    trigger(event) or
      raise InvalidState.new(msg(event))
  end

  def trigger?(event)
    raise InvalidEvent.new(msg(event)) unless @transitions_for.has_key?(event)

    @transitions_for[event].has_key?(state)
  end

  def events
    @transitions_for.keys.sort
  end

  def triggerable_events
    events.select { |event| trigger?(event) }.sort
  end

  def states
    @transitions_for.values.map(&:to_a).flatten.uniq.sort
  end

  def state=(state)
    @state = state
  end

 private
  def transit(event)
    callbacks = @callbacks_for[event][@state]
    @state = @transitions_for[event][@state]
    callbacks.each { |callback| callback.call(event) }
    true
  end

  def msg(event)
    "State: #{@state}; Event: #{event}"
  end
end

Version data entries

3 entries across 3 versions & 1 rubygems

Version Path
microfsm-0.1.2 lib/microfsm.rb
microfsm-0.1.1 lib/microfsm.rb
microfsm-0.1.0 lib/microfsm.rb