Class: HybridStateModel::StateMachine

Inherits:
Object
  • Object
show all
Defined in:
lib/hybrid_state_model/state_machine.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model_class) ⇒ StateMachine

Returns a new instance of StateMachine.



8
9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/hybrid_state_model/state_machine.rb', line 8

def initialize(model_class)
  @model_class = model_class
  @primary_states = []
  @micro_states = []
  @state_mappings = {}
  @callbacks = {
    before_primary_transition: {},
    after_primary_transition: {},
    before_micro_transition: {},
    after_micro_transition: {}
  }
  @auto_reset_micro = false
end

Instance Attribute Details

#auto_reset_microObject (readonly)

Returns the value of attribute auto_reset_micro.



5
6
7
# File 'lib/hybrid_state_model/state_machine.rb', line 5

def auto_reset_micro
  @auto_reset_micro
end

#callbacksObject (readonly)

Returns the value of attribute callbacks.



5
6
7
# File 'lib/hybrid_state_model/state_machine.rb', line 5

def callbacks
  @callbacks
end

#micro_fieldObject (readonly)

Returns the value of attribute micro_field.



5
6
7
# File 'lib/hybrid_state_model/state_machine.rb', line 5

def micro_field
  @micro_field
end

#micro_statesObject (readonly)

Returns the value of attribute micro_states.



5
6
7
# File 'lib/hybrid_state_model/state_machine.rb', line 5

def micro_states
  @micro_states
end

#model_classObject (readonly)

Returns the value of attribute model_class.



5
6
7
# File 'lib/hybrid_state_model/state_machine.rb', line 5

def model_class
  @model_class
end

#primary_fieldObject (readonly)

Returns the value of attribute primary_field.



5
6
7
# File 'lib/hybrid_state_model/state_machine.rb', line 5

def primary_field
  @primary_field
end

#primary_statesObject (readonly)

Returns the value of attribute primary_states.



5
6
7
# File 'lib/hybrid_state_model/state_machine.rb', line 5

def primary_states
  @primary_states
end

#state_mappingsObject (readonly)

Returns the value of attribute state_mappings.



5
6
7
# File 'lib/hybrid_state_model/state_machine.rb', line 5

def state_mappings
  @state_mappings
end

Instance Method Details

#after_micro_transition(states, &block) ⇒ Object



59
60
61
62
63
64
# File 'lib/hybrid_state_model/state_machine.rb', line 59

def after_micro_transition(states, &block)
  Array(states).each do |state|
    @callbacks[:after_micro_transition][state.to_sym] ||= []
    @callbacks[:after_micro_transition][state.to_sym] << block
  end
end

#after_primary_transition(states, &block) ⇒ Object



45
46
47
48
49
50
# File 'lib/hybrid_state_model/state_machine.rb', line 45

def after_primary_transition(states, &block)
  Array(states).each do |state|
    @callbacks[:after_primary_transition][state.to_sym] ||= []
    @callbacks[:after_primary_transition][state.to_sym] << block
  end
end

#before_micro_transition(states, &block) ⇒ Object



52
53
54
55
56
57
# File 'lib/hybrid_state_model/state_machine.rb', line 52

def before_micro_transition(states, &block)
  Array(states).each do |state|
    @callbacks[:before_micro_transition][state.to_sym] ||= []
    @callbacks[:before_micro_transition][state.to_sym] << block
  end
end

#before_primary_transition(states, &block) ⇒ Object



38
39
40
41
42
43
# File 'lib/hybrid_state_model/state_machine.rb', line 38

def before_primary_transition(states, &block)
  Array(states).each do |state|
    @callbacks[:before_primary_transition][state.to_sym] ||= []
    @callbacks[:before_primary_transition][state.to_sym] << block
  end
end

#can_transition_to_micro?(record, new_micro_state) ⇒ Boolean

Returns:

  • (Boolean)


107
108
109
110
111
112
113
114
115
116
# File 'lib/hybrid_state_model/state_machine.rb', line 107

def can_transition_to_micro?(record, new_micro_state)
  return false if new_micro_state.nil?

  current_primary = record.send(@primary_field)
  return false unless valid_micro_state?(new_micro_state, current_primary)

  # Check callbacks
  callbacks = @callbacks[:before_micro_transition][new_micro_state.to_sym] || []
  callbacks.all? { |cb| record.instance_exec(&cb) != false }
end

#can_transition_to_primary?(record, new_state) ⇒ Boolean

Returns:

  • (Boolean)


99
100
101
102
103
104
105
# File 'lib/hybrid_state_model/state_machine.rb', line 99

def can_transition_to_primary?(record, new_state)
  return false unless valid_primary_state?(new_state)

  # Check callbacks
  callbacks = @callbacks[:before_primary_transition][new_state.to_sym] || []
  callbacks.all? { |cb| record.instance_exec(&cb) != false }
end

#map(primary_state:, micro_states:) ⇒ Object



32
33
34
35
36
# File 'lib/hybrid_state_model/state_machine.rb', line 32

def map(primary_state:, micro_states:)
  primary_key = primary_state.to_sym
  micro_list = Array(micro_states).map(&:to_sym)
  @state_mappings[primary_key] = micro_list
end

#micro(field_name, states) ⇒ Object



27
28
29
30
# File 'lib/hybrid_state_model/state_machine.rb', line 27

def micro(field_name, states)
  @micro_field = field_name.to_sym
  @micro_states = states.map(&:to_sym)
end

#primary(field_name, states) ⇒ Object



22
23
24
25
# File 'lib/hybrid_state_model/state_machine.rb', line 22

def primary(field_name, states)
  @primary_field = field_name.to_sym
  @primary_states = states.map(&:to_sym)
end

#setup!Object

Raises:



70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/hybrid_state_model/state_machine.rb', line 70

def setup!
  raise Error, "Primary state field must be defined" unless @primary_field
  raise Error, "Micro state field must be defined" unless @micro_field
  raise Error, "Primary states must be defined" if @primary_states.empty?

  @model_class.include(Core)
  @model_class.include(TransitionMethods)
  @model_class.include(QueryMethods)
  @model_class.include(Metrics)

  setup_validations
  setup_callbacks
end

#valid_micro_state?(micro_state, primary_state) ⇒ Boolean

Returns:

  • (Boolean)


88
89
90
91
92
93
94
95
96
97
# File 'lib/hybrid_state_model/state_machine.rb', line 88

def valid_micro_state?(micro_state, primary_state)
  return true if micro_state.nil?

  primary_key = primary_state.to_sym
  allowed_micros = @state_mappings[primary_key]

  return true if allowed_micros.nil? || allowed_micros.empty?

  allowed_micros.include?(micro_state.to_sym)
end

#valid_primary_state?(state) ⇒ Boolean

Returns:

  • (Boolean)


84
85
86
# File 'lib/hybrid_state_model/state_machine.rb', line 84

def valid_primary_state?(state)
  @primary_states.include?(state.to_sym)
end

#when_primary_changes(reset_micro: false) ⇒ Object



66
67
68
# File 'lib/hybrid_state_model/state_machine.rb', line 66

def when_primary_changes(reset_micro: false)
  @auto_reset_micro = reset_micro
end