Last active
January 27, 2017 12:27
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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