Class: Foobara::StateMachine

Inherits:
Object
  • Object
show all
Includes:
Callbacks, Sugar, TransitionLog, Validations
Defined in:
foobara-0.0.110/projects/state_machine/src/sugar.rb,
foobara-0.0.110/projects/state_machine/src/callbacks.rb,
foobara-0.0.110/projects/state_machine/src/log_entry.rb,
foobara-0.0.110/projects/state_machine/src/validations.rb,
foobara-0.0.110/projects/state_machine/src/state_machine.rb,
foobara-0.0.110/projects/state_machine/src/transition_log.rb,
foobara-0.0.110/projects/state_machine/lib/foobara/state_machine.rb

Defined Under Namespace

Modules: Callbacks, Sugar, TransitionLog, Validations Classes: InvalidTransition, LogEntry

Class Attribute Summary collapse

Instance Attribute Summary collapse

Attributes included from TransitionLog

#log

Attributes included from Callbacks

#callback_registry

Class Method Summary collapse

Instance Method Summary collapse

Methods included from TransitionLog

#log_transition

Methods included from Concern

foobara_class_methods_module_for, foobara_concern?, included

Methods included from Callbacks

#register_transition_callback

Constructor Details

#initialize(*args, owner: nil, target_attribute: nil, **options) ⇒ StateMachine

owner is optional. It can help with certain callbacks. It’s also required if planning to use the target_attribute feature



41
42
43
44
45
46
47
48
49
50
51
# File 'foobara-0.0.110/projects/state_machine/src/state_machine.rb', line 41

def initialize(*args, owner: nil, target_attribute: nil, **options)
  self.owner = owner

  super

  if target_attribute
    self.target_attribute = target_attribute
  else
    self.current_state = self.class.initial_state
  end
end

Class Attribute Details

.initial_stateObject

Returns the value of attribute initial_state.



15
16
17
# File 'foobara-0.0.110/projects/state_machine/src/state_machine.rb', line 15

def initial_state
  @initial_state
end

.non_terminal_statesObject

Returns the value of attribute non_terminal_states.



15
16
17
# File 'foobara-0.0.110/projects/state_machine/src/state_machine.rb', line 15

def non_terminal_states
  @non_terminal_states
end

.raw_transition_mapObject

Returns the value of attribute raw_transition_map.



15
16
17
# File 'foobara-0.0.110/projects/state_machine/src/state_machine.rb', line 15

def raw_transition_map
  @raw_transition_map
end

.stateObject

Returns the value of attribute state.



15
16
17
# File 'foobara-0.0.110/projects/state_machine/src/state_machine.rb', line 15

def state
  @state
end

.statesObject

Returns the value of attribute states.



15
16
17
# File 'foobara-0.0.110/projects/state_machine/src/state_machine.rb', line 15

def states
  @states
end

.terminal_statesObject

Returns the value of attribute terminal_states.



15
16
17
# File 'foobara-0.0.110/projects/state_machine/src/state_machine.rb', line 15

def terminal_states
  @terminal_states
end

.transitionObject

Returns the value of attribute transition.



15
16
17
# File 'foobara-0.0.110/projects/state_machine/src/state_machine.rb', line 15

def transition
  @transition
end

.transition_mapObject

Returns the value of attribute transition_map.



15
16
17
# File 'foobara-0.0.110/projects/state_machine/src/state_machine.rb', line 15

def transition_map
  @transition_map
end

.transitionsObject

Returns the value of attribute transitions.



15
16
17
# File 'foobara-0.0.110/projects/state_machine/src/state_machine.rb', line 15

def transitions
  @transitions
end

Instance Attribute Details

#ownerObject

Returns the value of attribute owner.



37
38
39
# File 'foobara-0.0.110/projects/state_machine/src/state_machine.rb', line 37

def owner
  @owner
end

#target_attributeObject

Returns the value of attribute target_attribute.



37
38
39
# File 'foobara-0.0.110/projects/state_machine/src/state_machine.rb', line 37

def target_attribute
  @target_attribute
end

Class Method Details

.set_transition_map(transition_map, initial_state: nil, states: nil, terminal_states: nil, transitions: nil) ⇒ Object



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'foobara-0.0.110/projects/state_machine/src/state_machine.rb', line 18

def set_transition_map(transition_map, initial_state: nil, states: nil, terminal_states: nil, transitions: nil)
  self.raw_transition_map = transition_map

  self.initial_state = initial_state
  self.states = states
  self.terminal_states = terminal_states
  self.transitions = transitions

  desugarize_transition_map
  determine_states_and_transitions

  create_enums
  create_state_predicate_methods
  create_transition_methods
  create_can_methods
  create_register_callback_methods
end

Instance Method Details

#allowed_transitionsObject



94
95
96
97
98
99
100
# File 'foobara-0.0.110/projects/state_machine/src/state_machine.rb', line 94

def allowed_transitions
  if in_terminal_state?
    []
  else
    self.class.transition_map[current_state].keys
  end
end

#can?(transition) ⇒ Boolean

Returns:

  • (Boolean)


102
103
104
# File 'foobara-0.0.110/projects/state_machine/src/state_machine.rb', line 102

def can?(transition)
  self.class.transition_map[current_state].key?(transition)
end

#current_stateObject



53
54
55
56
57
58
59
# File 'foobara-0.0.110/projects/state_machine/src/state_machine.rb', line 53

def current_state
  if target_attribute
    owner.send(target_attribute) || self.class.initial_state
  else
    @current_state
  end
end

#current_state=(state) ⇒ Object



61
62
63
64
65
66
67
# File 'foobara-0.0.110/projects/state_machine/src/state_machine.rb', line 61

def current_state=(state)
  if target_attribute
    owner.send("#{target_attribute}=", state)
  else
    @current_state = state
  end
end

#in_terminal_state?Boolean

Returns:

  • (Boolean)


111
112
113
# File 'foobara-0.0.110/projects/state_machine/src/state_machine.rb', line 111

def in_terminal_state?
  self.class.terminal_states.include?(current_state)
end

#perform_transition!(transition, &block) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'foobara-0.0.110/projects/state_machine/src/state_machine.rb', line 69

def perform_transition!(transition, &block)
  from = current_state

  transition_map = self.class.transition_map

  if in_terminal_state?
    raise InvalidTransition,
          "#{current_state} is a terminal state so no transitions from here are allowed."
  end

  unless transition_map[current_state].key?(transition)
    raise InvalidTransition,
          "Cannot perform #{transition} from #{current_state}. Expected one of #{allowed_transitions}."
  end

  to = transition_map[current_state][transition]

  conditions = { from:, transition:, to: }

  callback_registry.runner(**conditions).callback_data(state_machine: self, **conditions).run do
    block.call if block_given?
    update_current_state(**conditions)
  end
end

#update_current_state(**conditions) ⇒ Object



106
107
108
109
# File 'foobara-0.0.110/projects/state_machine/src/state_machine.rb', line 106

def update_current_state(**conditions)
  self.current_state = conditions[:to]
  log_transition(**conditions)
end