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

Parameters:

  • object (Object)

    The object being transitioned

  • transition (Statesman::Transition)

    The transition

Returns:

  • (Hash)

    Event context



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

Parameters:

  • object (Object)

    The object to check

Returns:

  • (String)

    The effective current state (blank states become default)



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)

Parameters:

  • object (Object)

    The object with state_machine

  • target_state (String)

    The target state

Returns:

  • (Boolean)

    True if this is an idempotent transition



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

Parameters:

  • object (Object)

    The object

  • target_state (String)

    The target state

  • reason (String)

    The specific reason



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

Parameters:

  • object (Object)

    The object

  • current_state (String)

    The current state

  • target_state (String)

    The target state

  • reason (String)

    The reason for the restriction



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

Parameters:

  • object (Object)

    The object

  • target_state (String)

    The target state

  • result (Boolean)

    Whether the transition is allowed

  • reason (String)

    The reason for the result



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

Parameters:

  • object (Object)

    The object

Returns:

  • (String)

    The object identifier



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