Class: Stator::Integration

Inherits:
Object
  • Object
show all
Defined in:
lib/stator/integration.rb

Instance Method Summary collapse

Constructor Details

#initialize(machine, record) ⇒ Integration

Returns a new instance of Integration.



8
9
10
11
# File 'lib/stator/integration.rb', line 8

def initialize(machine, record)
  @machine = machine
  @record  = record
end

Instance Method Details

#in_state_at?(state, t) ⇒ Boolean

Returns:

  • (Boolean)


69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/stator/integration.rb', line 69

def in_state_at?(state, t)
  state = state.to_s
  t = t.to_time

  state_at = @record.send("#{state}_#{@machine.field}_at")

  # if we've never been in the state, the answer is no
  return false if state_at.nil?

  # if we came into this state later in life, the answer is no
  return false if state_at > t

  all_states = @machine.states.reverse

  # grab all the states and their timestamps that occur on or after state_at and on or before the time in question
  later_states = all_states.map do |s|

    next if state == s

    at = @record.send("#{s}_#{@machine.field}_at")

    next if at.nil?
    next if at < state_at
    next if at > t

    { state: s, at: at }
  end.compact

  # if there were no states on or after the state_at, the answer is yes
  return true if later_states.empty?

  # grab the states that were present at the lowest timestamp
  later_groups = later_states.group_by{|s| s[:at] }
  later_group_key = later_groups.keys.sort[0]
  later_states = later_groups[later_group_key]

  # if the lowest timestamp is the same as the state's timestamp, evaluate based on state index
  if later_states[0][:at] == state_at
    return all_states.index(state) < all_states.index(later_states[0][:state])
  end

  false
end

#invalid_state!Object

todo: i18n



52
53
54
# File 'lib/stator/integration.rb', line 52

def invalid_state!
  @record.errors.add(@machine.field, "is not a valid state")
end

#invalid_transition!(was, is) ⇒ Object



56
57
58
# File 'lib/stator/integration.rb', line 56

def invalid_transition!(was, is)
  @record.errors.add(@machine.field, "cannot transition to #{is.inspect} from #{was.inspect}")
end

#likely_state_at(t) ⇒ Object



113
114
115
# File 'lib/stator/integration.rb', line 113

def likely_state_at(t)
  @machine.states.reverse.detect{|s| in_state_at?(s,t) }
end

#stateObject



17
18
19
# File 'lib/stator/integration.rb', line 17

def state
  @record.send(@machine.field)
end

#state=(new_value) ⇒ Object



13
14
15
# File 'lib/stator/integration.rb', line 13

def state=(new_value)
  @record.send("#{@machine.field}=",  new_value)
end

#state_changed?(use_previous = false) ⇒ Boolean

Returns:

  • (Boolean)


29
30
31
32
33
34
35
# File 'lib/stator/integration.rb', line 29

def state_changed?(use_previous = false)
  if use_previous
    !!@record.previous_changes[@machine.field.to_s]
  else
    @record.send("#{@machine.field}_changed?")
  end
end

#state_was(use_previous = false) ⇒ Object



21
22
23
24
25
26
27
# File 'lib/stator/integration.rb', line 21

def state_was(use_previous = false)
  if use_previous
    @record.previous_changes[@machine.field.to_s].try(:[], 0)
  else
    @record.send("#{@machine.field}_was")
  end
end

#track_transitionObject



60
61
62
63
64
65
66
67
# File 'lib/stator/integration.rb', line 60

def track_transition
  return if @machine.skip_transition_tracking

  self.attempt_to_track_state(self.state)
  self.attempt_to_track_state_changed_timestamp

  true
end

#validate_transitionObject



37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/stator/integration.rb', line 37

def validate_transition
  return unless self.state_changed?
  return if @machine.skip_validations

  was = self.state_was
  is  = self.state

  if @record.new_record?
    invalid_state! unless @machine.matching_transition(::Stator::Transition::ANY, is)
  else
    invalid_transition!(was, is) unless @machine.matching_transition(was, is)
  end
end