Skip to content

Instantly share code, notes, and snippets.

@Thermatix
Last active January 27, 2017 12:27
Show Gist options
  • Save Thermatix/7cd6a680e2890a291ced to your computer and use it in GitHub Desktop.
Save Thermatix/7cd6a680e2890a291ced to your computer and use it in GitHub Desktop.
A simple state machine for react.rb(reactive-ruby), provides useful dsl to make building components easier and more concise
module React_State_Machine
def check_intial_state
raise "no initial state set, please use `set_initial_state STATE`" unless get_current_state
end
def get_current_state
send(self.class.state_name)
end
def set_current_state value
send("#{self.class.state_name}=",value)
end
def use_(callback)
if callback
if callback.lambda?
callback.call
else
send(callback)
end
end
end
def can_transition_(from)
[from].flatten.include?(get_current_state)
end
def using_state_action
action = self.class.state_actions[get_current_state]
if action.respond_to?(:call)
self.instance_eval(&action)
else
send(action)
end
end
module API
def state_action state, func_name=nil, &action
@state_actions ||= {}
if state.kind_of?(Array)
state.each { |name| @state_actions[name] = func_name || action }
else
@state_actions[state] = func_name || action
end
end
def state_actions
@state_actions
end
def state_name
@state_name || 'current_state'
end
def set_state_name name
@state_name = name
end
def create_state state
@states ||= []
@states << state
define_method "#{state}?" do
check_intial_state
get_current_state == state
end
end
def create_states states
states.each do |state|
create_state state
end
end
def set_initial_state state
@initial_state = state
define_state(state_name){state}
end
def event name,data, &callback
@events ||= []
@events << name
define_method "#{name}!" do |*args|
check_intial_state
use_(data[:before])
if can_transition_(data[:from])
set_current_state data[:to]
callback.call(*args) if block_given?
else
use_(data[:fail])
end
end
define_method "may_#{name}?" do
check_intial_state
get_current_state == data[:from]
end
end
end
def self.included(base)
base.extend API
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment