Sha256: 68c170999c4509eb4925ac7c0b4f7baca0a90e3221722c99e2dc4b2310e03de2

Contents?: true

Size: 1.46 KB

Versions: 4

Compression:

Stored size: 1.46 KB

Contents

# frozen_string_literal: true

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

  attr_accessor :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
    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

  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

4 entries across 4 versions & 1 rubygems

Version Path
microfsm-0.1.10 lib/microfsm.rb
microfsm-0.1.7 lib/microfsm.rb
microfsm-0.1.6 lib/microfsm.rb
microfsm-0.1.4 lib/microfsm.rb