Skip to content

Instantly share code, notes, and snippets.

@reggieb
Last active August 29, 2015 14:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save reggieb/4f4863a3e43ff49317ab to your computer and use it in GitHub Desktop.
Save reggieb/4f4863a3e43ff49317ab to your computer and use it in GitHub Desktop.
Rollback persisted finite machine: An example
class WorkRequest < ActiveRecord::Base
# Attributes include :state_history (text) and :state (string)
serialize :state_history, Array
after_find :restore_process
after_initialize :restore_process
def rollback_state_to_previous
previous_state = state_history.pop
return unless previous_state
process.restore! previous_state.to_sym
self.state = previous_state
save
end
def process
@process ||= new_process
end
delegate :request, :submit, to: :process
private
def new_process
new_process = WorkRequestProcess.new
new_process.target(self)
new_process
end
def restore_process
process.restore!(state.to_sym) if state.present?
end
end
class WorkRequestProcess < FiniteMachine::Definition
initial :draft
alias_target :work_request
events {
event :request, {
:draft => :requested
}
event :submit, {
:requested => :submitted
}
}
callbacks {
on_transition do |event|
work_request.state = event.to
work_request.state_history << event.from
work_request.save
end
}
end
@reggieb
Copy link
Author

reggieb commented Jan 7, 2015

A work request starts in the draft state. To move to the next state:

work_request.request

This triggers the request event and the new state is stored in work_request#state, and the previous state is added to state_history

work_request.state               == 'requested'
work_request.state_history  == ['draft']

The work request can then be progressed to the next state:

work_request.submit

Which changes the stored attributes to:

work_request.state               == 'submitted'
work_request.state_history  == ['draft', 'requested']

To roll back:

work_request.rollback_state_to_previous

Which returns the stored attributes to:

work_request.state               == 'requested'
work_request.state_history  == ['draft']

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment