Module: Statesman::Machine::ClassMethods

Defined in:
lib/statesman/machine.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#initial_stateObject (readonly)

Returns the value of attribute initial_state.



30
31
32
# File 'lib/statesman/machine.rb', line 30

def initial_state
  @initial_state
end

Instance Method Details

#after_guard_failure(options = {}, &block) ⇒ Object



122
123
124
125
# File 'lib/statesman/machine.rb', line 122

def after_guard_failure(options = {}, &block)
  add_callback(callback_type: :after_guard_failure, callback_class: Callback,
               from: options[:from], to: options[:to], &block)
end

#after_transition(options = { after_commit: false }, &block) ⇒ Object



110
111
112
113
114
115
# File 'lib/statesman/machine.rb', line 110

def after_transition(options = { after_commit: false }, &block)
  callback_type = options[:after_commit] ? :after_commit : :after

  add_callback(callback_type: callback_type, callback_class: Callback,
               from: options[:from], to: options[:to], &block)
end

#after_transition_failure(options = {}, &block) ⇒ Object



117
118
119
120
# File 'lib/statesman/machine.rb', line 117

def after_transition_failure(options = {}, &block)
  add_callback(callback_type: :after_transition_failure, callback_class: Callback,
               from: options[:from], to: options[:to], &block)
end

#before_transition(options = {}, &block) ⇒ Object



100
101
102
103
# File 'lib/statesman/machine.rb', line 100

def before_transition(options = {}, &block)
  add_callback(callback_type: :before, callback_class: Callback,
               from: options[:from], to: options[:to], &block)
end

#callbacksObject



62
63
64
65
66
67
68
69
70
71
# File 'lib/statesman/machine.rb', line 62

def callbacks
  @callbacks ||= {
    before: [],
    after: [],
    after_transition_failure: [],
    after_guard_failure: [],
    after_commit: [],
    guards: [],
  }
end

#guard_transition(options = {}, &block) ⇒ Object



105
106
107
108
# File 'lib/statesman/machine.rb', line 105

def guard_transition(options = {}, &block)
  add_callback(callback_type: :guards, callback_class: Guard,
               from: options[:from], to: options[:to], &block)
end

#remove_state(state_name) ⇒ Object



47
48
49
50
51
52
53
54
55
56
# File 'lib/statesman/machine.rb', line 47

def remove_state(state_name)
  state_name = state_name.to_s

  remove_transitions(from: state_name)
  remove_transitions(to: state_name)
  remove_callbacks(from: state_name)
  remove_callbacks(to: state_name)

  @states.delete(state_name.to_s)
end

#remove_transitions(from: nil, to: nil) ⇒ Object

Raises:

  • (ArgumentError)


86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/statesman/machine.rb', line 86

def remove_transitions(from: nil, to: nil)
  raise ArgumentError, "Both from and to can't be nil!" if from.nil? && to.nil?
  return if successors.nil?

  if from.present?
    @successors[from.to_s].delete(to.to_s) if to.present?
    @successors.delete(from.to_s) if to.nil? || successors[from.to_s].empty?
  elsif to.present?
    @successors.
      transform_values! { |to_states| to_states - [to.to_s] }.
      filter! { |_from_state, to_states| to_states.any? }
  end
end

#state(name, options = { initial: false }) ⇒ Object



36
37
38
39
40
41
42
43
44
45
# File 'lib/statesman/machine.rb', line 36

def state(name, options = { initial: false })
  name = name.to_s
  if options[:initial]
    validate_initial_state(name)
    @initial_state = name
  end
  define_state_constant(name)

  states << name
end

#statesObject



32
33
34
# File 'lib/statesman/machine.rb', line 32

def states
  @states ||= []
end

#successorsObject



58
59
60
# File 'lib/statesman/machine.rb', line 58

def successors
  @successors ||= {}
end

#transition(from: nil, to: nil) ⇒ Object

Raises:



73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/statesman/machine.rb', line 73

def transition(from: nil, to: nil)
  from = to_s_or_nil(from)
  to = array_to_s_or_nil(to)

  raise InvalidStateError, "No to states provided." if to.empty?

  successors[from] ||= []

  ([from] + to).each { |state| validate_state(state) }

  successors[from] += to
end

#validate_callback_condition(options = { from: nil, to: nil }) ⇒ Object



127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/statesman/machine.rb', line 127

def validate_callback_condition(options = { from: nil, to: nil })
  from = to_s_or_nil(options[:from])
  to   = array_to_s_or_nil(options[:to])

  ([from] + to).compact.each { |state| validate_state(state) }
  return if from.nil? && to.empty?

  validate_not_from_terminal_state(from)
  to.each { |state| validate_not_to_initial_state(state) }

  return if from.nil? || to.empty?

  to.each { |state| validate_from_and_to_state(from, state) }
end

#validate_from_and_to_state(from, to) ⇒ Object

Check that the transition is valid when ‘from’ and ‘to’ are given



159
160
161
162
163
164
# File 'lib/statesman/machine.rb', line 159

def validate_from_and_to_state(from, to)
  unless successors.fetch(from, []).include?(to)
    raise InvalidTransitionError,
          "Cannot transition from '#{from}' to '#{to}'"
  end
end

#validate_not_from_terminal_state(from) ⇒ Object

Check that the ‘from’ state is not terminal



143
144
145
146
147
148
# File 'lib/statesman/machine.rb', line 143

def validate_not_from_terminal_state(from)
  unless from.nil? || successors.key?(from)
    raise InvalidTransitionError,
          "Cannot transition away from terminal state '#{from}'"
  end
end

#validate_not_to_initial_state(to) ⇒ Object

Check that the ‘to’ state is not initial



151
152
153
154
155
156
# File 'lib/statesman/machine.rb', line 151

def validate_not_to_initial_state(to)
  unless to.nil? || successors.values.flatten.include?(to)
    raise InvalidTransitionError,
          "Cannot transition to initial state '#{to}'"
  end
end