Skip to content

Instantly share code, notes, and snippets.

@RomanTurner
Created April 7, 2024 23:44
Show Gist options
  • Save RomanTurner/0208ebf4fcaae7a741f6e236e9382db1 to your computer and use it in GitHub Desktop.
Save RomanTurner/0208ebf4fcaae7a741f6e236e9382db1 to your computer and use it in GitHub Desktop.
Ruby Simple Event as State Machine
module Event
class Base < ActiveRecord::Base
self.table_name = 'events'
# Callbacks to enforce state transitions logic
before_update :validate_status_transition
enum status: {
enqueued: 0,
processing: 1,
completed: 2,
failed: 3
}
# Transactional work processing
def process
ActiveRecord::Base.transaction do
update!(status: :processing)
yield(self)
update!(status: :completed)
rescue StandardError => e
current_data = data || {}
update!(status: :failed, data: current_data.merge('error' => e.message))
raise ActiveRecord::Rollback
end
end
def perform_async
EventJob.perform_async(id)
end
def perform_now
EventJob.perform_now(id)
end
def perform_later(...)
EventJob.perform_later(...)
end
private
def validate_status_transition
return if status_changed? && valid_transition?
errors.add(:status, 'transition is not allowed')
throw(:abort)
end
def valid_transition?
case status_was
when 'enqueued'
processing?
when 'processing'
completed? || failed?
when 'completed', 'failed'
false # No transitions allowed from completed or failed
else
true # for new records
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment