Skip to content

Instantly share code, notes, and snippets.

@ta1kt0me
Created November 15, 2020 16:01
Show Gist options
  • Save ta1kt0me/60bc87e4f51b463454dfbc769580c77d to your computer and use it in GitHub Desktop.
Save ta1kt0me/60bc87e4f51b463454dfbc769580c77d to your computer and use it in GitHub Desktop.
SimpleStateManager for PORO
module SimpleStateManager
class InvalidTransitionError < StandardError; end
def self.included(klass)
klass.extend(ClassMethods)
attr_accessor :state
klass.class_eval do
original_method = instance_method(:initialize)
define_method(:initialize) do |*args, &block|
original_method.bind(self).call(*args, &block)
@state = klass.instance_variable_get(:@default_state)
end
end
end
module ClassMethods
# def default_state(default)
# @default_state = default
# end
def state(key, values)
if values.key?(:as)
@default_state = key if values[:as] == :default
values.merge!(to: :nil) if values[:as] == :finish
end
@transitions ||= {}
@transitions[key] = values
end
def event(name, to:, &block)
@events ||= {}
@events[name] = {
to: to || [],
}
define_method(name) do
raise InvalidTransitionError if state.nil?
events = self.class.instance_variable_get(:@events)
transitions = self.class.instance_variable_get(:@transitions)
to = events[name][:to]
raise InvalidTransitionError unless transitions[state][:to].include?(to)
self.state = to
block.call(self) if !block.nil?
end
end
end
end
class Sample
include SimpleStateManager
# default_state :first
state :first, to: [:second, :last], as: :default
state :second, to: [:third]
state :third, to: [:last]
state :last, as: :finish
event(:move_second, to: :second) { |obj| obj.go_two }
event(:move_third, to: :third) { |obj| obj.go_three }
event(:move_last, to: :last) { |obj| obj.go_last }
def go_two
puts "go2"
end
def go_three
puts "go3"
end
def go_last
puts "last!!!!"
end
end
s = Sample.new
s.move_second
s.move_third
s.move_last
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment