Skip to content

Instantly share code, notes, and snippets.

@roovo
Created April 9, 2009 09:25
Show Gist options
  • Save roovo/92346 to your computer and use it in GitHub Desktop.
Save roovo/92346 to your computer and use it in GitHub Desktop.
module DataMapper
module Is
module StateMachine
# hook may be either a Proc or symbol
def run_hook_if_present(hook)
return true unless hook
if hook.respond_to?(:call)
hook.call(self)
else
self.send(hook)
end
end
module EventDsl
def transition(options)
unless state_machine_context?(:event)
raise InvalidContext, "Valid only in 'event' block"
end
event_name = @is_state_machine[:event][:name]
event_object = @is_state_machine[:event][:object]
from = options[:from]
to = options[:to]
guard = options[:guard]
event_object.add_transition(from, to, guard)
end
end
module Data
class Event
def add_transition(from, to, guard)
@transitions << { :from => from, :to => to, :guard => guard }
end
end
class Machine
def fire_event(event_name, resource)
unless event = find_event(event_name)
raise InvalidEvent, "Could not find event (#{event_name.inspect})"
end
transition = event.transitions.find do |t|
t[:from].to_s == @current_state_name.to_s
end
unless transition
raise InvalidEvent, "Event (#{event_name.inspect}) does not" +
"exist for current state (#{@current_state_name.inspect})"
end
# == Run transition :guard hook (if present) ==
return unless resource.run_hook_if_present(transition[:guard])
# == Run :exit hook (if present) ==
resource.run_hook_if_present current_state.options[:exit]
# == Change the current_state ==
@current_state_name = transition[:to]
# == Run :enter hook (if present) ==
resource.run_hook_if_present current_state.options[:enter]
end
end
end # module Data
end # module StateMachine
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment