class NxtStateMachine::StateMachine
Attributes
callbacks[R]
class_context[R]
defuse_registry[R]
error_callback_registry[R]
events[R]
initial_state[RW]
name[R]
options[R]
Public Class Methods
new(name, class_context, event_registry, **opts)
click to toggle source
# File lib/nxt_state_machine/state_machine.rb, line 3 def initialize(name, class_context, event_registry, **opts) @name = name @class_context = class_context @options = opts @states = NxtStateMachine::StateRegistry.new @transitions = [] @events = event_registry @callbacks = CallbackRegistry.new @error_callback_registry = ErrorCallbackRegistry.new @defuse_registry = DefuseRegistry.new @initial_state = nil end
Public Instance Methods
after_transition(from:, to:, run: nil, &block)
click to toggle source
# File lib/nxt_state_machine/state_machine.rb, line 117 def after_transition(from:, to:, run: nil, &block) callbacks.register(from, to, :after, run, block) end
all_states_except(*excluded)
click to toggle source
# File lib/nxt_state_machine/state_machine.rb, line 80 def all_states_except(*excluded) all_states - excluded end
all_transitions_from_to(from: all_states, to: all_states)
click to toggle source
# File lib/nxt_state_machine/state_machine.rb, line 66 def all_transitions_from_to(from: all_states, to: all_states) transitions.select { |transition| transition.transitions_from_to?(from, to) } end
any_state()
click to toggle source
# File lib/nxt_state_machine/state_machine.rb, line 74 def any_state states.values.map(&:enum) end
Also aliased as: all_states
around_transition(from:, to:, run: nil, &block)
click to toggle source
# File lib/nxt_state_machine/state_machine.rb, line 137 def around_transition(from:, to:, run: nil, &block) callbacks.register(from, to, :around, run, block) end
before_transition(from:, to:, run: nil, &block)
click to toggle source
# File lib/nxt_state_machine/state_machine.rb, line 113 def before_transition(from:, to:, run: nil, &block) callbacks.register(from, to, :before, run, block) end
can_transition!(event, from)
click to toggle source
# File lib/nxt_state_machine/state_machine.rb, line 108 def can_transition!(event, from) return true if can_transition?(event, from) raise NxtStateMachine::Errors::TransitionNotDefined, "No transition :#{event} for state :#{from} defined" end
can_transition?(event_name, from)
click to toggle source
# File lib/nxt_state_machine/state_machine.rb, line 103 def can_transition?(event_name, from) event = events.resolve!(event_name) event && event.event_transitions.key?(from) end
configure(&block)
click to toggle source
# File lib/nxt_state_machine/state_machine.rb, line 141 def configure(&block) instance_exec(&block) self end
current_state_name(context)
click to toggle source
# File lib/nxt_state_machine/state_machine.rb, line 174 def current_state_name(context) Callable.new(get_state_with).bind(context).call(target(context)) end
defuse(errors = [], from:, to:)
click to toggle source
# File lib/nxt_state_machine/state_machine.rb, line 125 def defuse(errors = [], from:, to:) defuse_registry.register(from, to, errors) end
event(name, **options, &block)
click to toggle source
# File lib/nxt_state_machine/state_machine.rb, line 84 def event(name, **options, &block) name = name.to_sym event = Event.new(name, self, **options, &block) events.register(name, event) Event::Names.set_state_method_map(name).each do |event_name, set_state_method| class_context.define_method event_name do |*args, **opts| event.state_machine.can_transition!(name, event.state_machine.current_state_name(self)) transition = event.event_transitions.resolve!(event.state_machine.current_state_name(self)) # Transition is build every time and thus should be thread safe! transition.build_transition(event, self, set_state_method, *args, **opts) end end class_context.define_method "can_#{name}?" do event.state_machine.can_transition?(name, event.state_machine.current_state_name(self)) end end
events_for_state(state)
click to toggle source
# File lib/nxt_state_machine/state_machine.rb, line 70 def events_for_state(state) events.values.select { |event| event.transitions_from?(state) } end
find_error_callback(error, transition)
click to toggle source
# File lib/nxt_state_machine/state_machine.rb, line 159 def find_error_callback(error, transition) error_callback_registry.resolve(error, transition) end
get_state_with(method = nil, &block)
click to toggle source
# File lib/nxt_state_machine/state_machine.rb, line 21 def get_state_with(method = nil, &block) @get_state_with ||= (method || block) || raise_missing_configuration_error(:get_state_with) end
on_error(error = StandardError, from:, to:, run: nil, &block)
click to toggle source
# File lib/nxt_state_machine/state_machine.rb, line 129 def on_error(error = StandardError, from:, to:, run: nil, &block) error_callback_registry.register(from, to, error, run, block) end
on_error!(error = StandardError, from:, to:, run: nil, &block)
click to toggle source
# File lib/nxt_state_machine/state_machine.rb, line 133 def on_error!(error = StandardError, from:, to:, run: nil, &block) error_callback_registry.register!(from, to, error, run, block) end
on_success(from:, to:, run: nil, &block)
click to toggle source
# File lib/nxt_state_machine/state_machine.rb, line 121 def on_success(from:, to:, run: nil, &block) callbacks.register(from, to, :success, run, block) end
run_after_callbacks(transition, context)
click to toggle source
# File lib/nxt_state_machine/state_machine.rb, line 151 def run_after_callbacks(transition, context) run_callbacks(transition, :after, context) end
run_before_callbacks(transition, context)
click to toggle source
TODO: Everything that require context should live in some sort of proxy
# File lib/nxt_state_machine/state_machine.rb, line 147 def run_before_callbacks(transition, context) run_callbacks(transition, :before, context) end
run_callbacks(transition, kind, context)
click to toggle source
# File lib/nxt_state_machine/state_machine.rb, line 163 def run_callbacks(transition, kind, context) current_callbacks = callbacks.resolve!(transition, kind) return unless current_callbacks.any? current_callbacks.each do |callback| Callable.new(callback).bind(context).call(transition) end true end
run_success_callbacks(transition, context)
click to toggle source
# File lib/nxt_state_machine/state_machine.rb, line 155 def run_success_callbacks(transition, context) run_callbacks(transition, :success, context) end
set_state_with(method = nil, &block)
click to toggle source
# File lib/nxt_state_machine/state_machine.rb, line 25 def set_state_with(method = nil, &block) @set_state_with ||= (method || block) || raise_missing_configuration_error(:set_state_with) end
set_state_with!(method = nil, &block)
click to toggle source
# File lib/nxt_state_machine/state_machine.rb, line 29 def set_state_with!(method = nil, &block) @set_state_with_bang ||= (method || block) || raise_missing_configuration_error(:set_state_with!) end
state(*names, **opts, &block)
click to toggle source
# File lib/nxt_state_machine/state_machine.rb, line 33 def state(*names, **opts, &block) defaults = { initial: false } opts.reverse_merge!(defaults) machine = self Array(names).map do |name| if opts.fetch(:initial) && initial_state.present? raise NxtStateMachine::Errors::InitialStateAlreadyDefined, ":#{initial_state.enum} was already defined as the initial state" else state = new_state_class(&block).new(name, self, **opts.reverse_merge(index: states.size)) states.register(name, state) self.initial_state = state if opts.fetch(:initial) class_context.define_method "#{name}?" do machine.current_state_name(self) == name end state end end end
states(*names, **opts, &block)
click to toggle source
# File lib/nxt_state_machine/state_machine.rb, line 55 def states(*names, **opts, &block) # method overloading in ruby ;-) return @states unless names.any? state(*names, **opts, &block) end
target(context)
click to toggle source
# File lib/nxt_state_machine/state_machine.rb, line 178 def target(context) @target_method ||= (options[:target] || :itself) context.send(@target_method) end
transitions()
click to toggle source
# File lib/nxt_state_machine/state_machine.rb, line 62 def transitions @transitions ||= events.values.flat_map(&:event_transitions) end
Private Instance Methods
new_state_class(&block)
click to toggle source
# File lib/nxt_state_machine/state_machine.rb, line 189 def new_state_class(&block) if block Class.new(NxtStateMachine::State, &block) else NxtStateMachine::State end end
raise_missing_configuration_error(method)
click to toggle source
# File lib/nxt_state_machine/state_machine.rb, line 185 def raise_missing_configuration_error(method) raise NxtStateMachine::Errors::MissingConfiguration, "Configuration method :#{method} was not defined" end