Class: FiniteMachine::DSL

Inherits:
GenericDSL show all
Includes:
Safety
Defined in:
lib/finite_machine/dsl.rb

Overview

A class responsible for adding state machine specific dsl

Constant Summary

Constants included from Safety

Safety::CALLBACK_INVALID_MESSAGE, Safety::EVENT_CALLBACK_CONFLICT_MESSAGE, Safety::EVENT_CONFLICT_MESSAGE, Safety::STATE_CALLBACK_CONFLICT_MESSAGE

Instance Method Summary collapse

Methods included from Safety

#detect_event_conflict!, #ensure_valid_callback_name!

Methods inherited from GenericDSL

#any_event, #any_state, #call, #method_missing, #respond_to_missing?

Constructor Details

#initialize(machine, attrs) ⇒ DSL

Initialize top level DSL



63
64
65
66
67
68
69
70
71
72
73
# File 'lib/finite_machine/dsl.rb', line 63

def initialize(machine, attrs)
  super(machine, attrs)

  @machine.state = FiniteMachine::DEFAULT_STATE
  @defer_initial = true
  @silent_initial = true

  initial(@attrs[:initial])   if @attrs[:initial]
  terminal(@attrs[:terminal]) if @attrs[:terminal]
  log_transitions(@attrs.fetch(:log_transitions, false))
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class FiniteMachine::GenericDSL

Instance Method Details

#alias_target(*aliases) ⇒ Object

Add aliases for the target object

Examples:

FiniteMachine.define do
  target_alias :engine

  on_transition do |event|
    engine.state = event.to
  end
end

Parameters:

  • aliases (Array<Symbol>)

    the names for target alias



90
91
92
93
94
95
96
# File 'lib/finite_machine/dsl.rb', line 90

def alias_target(*aliases)
  aliases.each do |alias_name|
    next if env.aliases.include?(alias_name)

    env.aliases << alias_name
  end
end

#event(name, transitions = {}, &block) ⇒ Transition

Create event and associate transition

Examples:

event :go, :green => :yellow
event :go, :green => :yellow, if: :lights_on?

Parameters:

  • name (Symbol)

    the event name

  • transitions (Hash) (defaults to: {})

    the event transitions and conditions

Returns:



172
173
174
175
176
177
178
179
180
181
182
# File 'lib/finite_machine/dsl.rb', line 172

def event(name, transitions = {}, &block)
  detect_event_conflict!(name) if machine.auto_methods?

  if block_given?
    merger = ChoiceMerger.new(machine, name, transitions)
    merger.instance_eval(&block)
  else
    transition_builder = TransitionBuilder.new(machine, name, transitions)
    transition_builder.call(transitions)
  end
end

#handle(*exceptions, &block) ⇒ Array[Exception]

Add error handler

Examples:

handle InvalidStateError, with: :log_errors

Parameters:

  • exceptions (Array)

Returns:

  • (Array[Exception])


194
195
196
# File 'lib/finite_machine/dsl.rb', line 194

def handle(*exceptions, &block)
  @machine.handle(*exceptions, &block)
end

#initial(value, options = {}) ⇒ StateMachine

Define initial state

Examples:

initial :green

Defer initial event

initial state: green, defer: true

Trigger callbacks

initial :green, silent: false

Redefine event name

initial :green, event: :start

Parameters:

  • value (Symbol)

    The initial state name.

  • options (Hash[Symbol]) (defaults to: {})
  • value (String, Hash)

Options Hash (options):

  • :event (Symbol)

    The event name.

  • :defer (Symbol)

    Set to true to defer initial state transition. Default false.

  • :silent (Symbol)

    Set to true to disable callbacks. Default true.

Returns:



129
130
131
132
133
134
# File 'lib/finite_machine/dsl.rb', line 129

def initial(value, options = {})
  state = (value && !value.is_a?(Hash)) ? value : raise_missing_state
  name, @defer_initial, @silent_initial = *parse_initial(options)
  @initial_event = name
  event(name, FiniteMachine::DEFAULT_STATE => state, silent: @silent_initial)
end

#log_transitions(value) ⇒ Object

Decide whether to log transitions



201
202
203
# File 'lib/finite_machine/dsl.rb', line 201

def log_transitions(value)
  self.log_transitions = value
end

#terminal(*values) ⇒ FiniteMachine::StateMachine

Define terminal state

Examples:

terminal :red

Returns:



154
155
156
# File 'lib/finite_machine/dsl.rb', line 154

def terminal(*values)
  self.terminal_states = values
end

#trigger_initnil

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Trigger initial event

Returns:

  • (nil)


141
142
143
144
# File 'lib/finite_machine/dsl.rb', line 141

def trigger_init
  method = @silent_initial ? :transition : :trigger
  @machine.public_send(method, :"#{@initial_event}") unless @defer_initial
end