Module: Tasker::Concerns::StateMachineBase::ClassMethods

Defined in:
lib/tasker/concerns/state_machine_base.rb

Instance Method Summary collapse

Instance Method Details

#build_event_context(object, transition) ⇒ Hash

Build event context appropriate for the object type



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/tasker/concerns/state_machine_base.rb', line 108

def build_event_context(object, transition)
  base_context = {
    from_state: transition.from_state,
    to_state: transition.to_state,
    transitioned_at: Time.zone.now
  }

  case object.class.name
  when /Task/
    base_context.merge(
      task_id: object.task_id,
      task_name: object.name,
      task_context: object.respond_to?(:context) ? object.context : nil
    )
  when /WorkflowStep/
    base_context.merge(
      task_id: object.task_id,
      step_id: object.workflow_step_id,
      step_name: object.name
    )
  else
    base_context.merge(
      object_id: object.id,
      object_type: object.class.name
    )
  end
end

#effective_current_state(object) ⇒ String

Get the effective current state, handling blank/empty states



75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/tasker/concerns/state_machine_base.rb', line 75

def effective_current_state(object)
  current_state = object.state_machine.current_state

  current_state.presence || case object.class.name
                            when /Task/
                              Constants::TaskStatuses::PENDING
                            when /WorkflowStep/
                              Constants::WorkflowStepStatuses::PENDING
                            else
                              current_state
                            end
end

#idempotent_transition?(object, target_state) ⇒ Boolean

Check if a transition is idempotent (current state == target state)



58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/tasker/concerns/state_machine_base.rb', line 58

def idempotent_transition?(object, target_state)
  effective_state = effective_current_state(object)
  is_idempotent = effective_state == target_state

  if is_idempotent
    Rails.logger.debug do
      "#{object.class.name}: Detected idempotent transition to #{target_state} for #{object_id(object)}"
    end
  end

  is_idempotent
end

#log_condition_not_met(object, target_state, reason) ⇒ Object

Log when dependencies/conditions are not met



162
163
164
165
166
# File 'lib/tasker/concerns/state_machine_base.rb', line 162

def log_condition_not_met(object, target_state, reason)
  Rails.logger.debug do
    "#{name}: Cannot transition #{object.class.name} #{object_id(object)} to #{target_state} - #{reason}"
  end
end

#log_invalid_from_state(object, current_state, target_state, reason) ⇒ Object

Log an invalid from-state transition



150
151
152
153
154
155
# File 'lib/tasker/concerns/state_machine_base.rb', line 150

def log_invalid_from_state(object, current_state, target_state, reason)
  Rails.logger.debug do
    "#{name}: Cannot transition to #{target_state} from '#{current_state}' " \
      "(#{object.class.name} #{object_id(object)}). #{reason}."
  end
end

#log_transition_result(object, target_state, result, reason) ⇒ Object

Log the result of a transition check



174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/tasker/concerns/state_machine_base.rb', line 174

def log_transition_result(object, target_state, result, reason)
  object_identifier = "#{object.class.name} #{object_id(object)}"
  if result
    Rails.logger.debug do
      "#{name}: Allowing transition to #{target_state} for #{object_identifier} (#{reason})"
    end
  else
    Rails.logger.debug do
      "#{name}: Blocking transition to #{target_state} for #{object_identifier} (#{reason} failed)"
    end
  end
end

#object_id(object) ⇒ String

Get a consistent object identifier for logging



92
93
94
95
96
97
98
99
100
101
# File 'lib/tasker/concerns/state_machine_base.rb', line 92

def object_id(object)
  case object.class.name
  when /Task/
    object.task_id
  when /WorkflowStep/
    object.workflow_step_id
  else
    object.id
  end
end