module Workflow::InstanceMethods
Public Instance Methods
current_state()
click to toggle source
# File lib/workflow.rb, line 79 def current_state loaded_state = load_workflow_state res = spec.states[loaded_state.to_sym] if loaded_state res || spec.initial_state end
halt(reason = nil)
click to toggle source
# File lib/workflow.rb, line 134 def halt(reason = nil) @halted_because = reason @halted = true end
halt!(reason = nil)
click to toggle source
# File lib/workflow.rb, line 139 def halt!(reason = nil) @halted_because = reason @halted = true raise TransitionHalted.new(reason) end
halted?()
click to toggle source
See the 'Guards' section in the README @return true if the last transition was halted by one of the transition callbacks.
# File lib/workflow.rb, line 87 def halted? @halted end
halted_because()
click to toggle source
@return the reason of the last transition abort as set by the previous call of `halt` or `halt!` method.
# File lib/workflow.rb, line 93 def halted_because @halted_because end
process_event!(name, *args)
click to toggle source
# File lib/workflow.rb, line 97 def process_event!(name, *args) event = current_state.events.first_applicable(name, self) raise NoTransitionAllowed.new( "There is no event #{name.to_sym} defined for the #{current_state} state") \ if event.nil? @halted_because = nil @halted = false check_transition(event) from = current_state to = spec.states[event.transitions_to] run_before_transition(from, to, name, *args) return false if @halted begin return_value = run_action(event.action, *args) || run_action_callback(event.name, *args) rescue StandardError => e run_on_error(e, from, to, name, *args) end return false if @halted run_on_transition(from, to, name, *args) run_on_exit(from, to, name, *args) transition_value = persist_workflow_state to.to_s run_on_entry(to, from, name, *args) run_after_transition(from, to, name, *args) return_value.nil? ? transition_value : return_value end
spec()
click to toggle source
# File lib/workflow.rb, line 145 def spec # check the singleton class first class << self return workflow_spec if workflow_spec end c = self.class # using a simple loop instead of class_inheritable_accessor to avoid # dependency on Rails' ActiveSupport until c.workflow_spec || !(c.include? Workflow) c = c.superclass end c.workflow_spec end
Private Instance Methods
check_transition(event)
click to toggle source
# File lib/workflow.rb, line 162 def check_transition(event) # Create a meaningful error message instead of # "undefined method `on_entry' for nil:NilClass" # Reported by Kyle Burton if !spec.states[event.transitions_to] raise WorkflowError.new("Event[#{event.name}]'s " + "transitions_to[#{event.transitions_to}] is not a declared state.") end end
has_callback?(action)
click to toggle source
# File lib/workflow.rb, line 199 def has_callback?(action) # 1. public callback method or # 2. protected method somewhere in the class hierarchy or # 3. private in the immediate class (parent classes ignored) action = action.to_sym self.respond_to?(action) or self.class.protected_method_defined?(action) or self.private_methods(false).map(&:to_sym).include?(action) end
load_workflow_state()
click to toggle source
load_workflow_state
and persist_workflow_state
can be overriden to handle the persistence of the workflow state.
Default (non ActiveRecord) implementation stores the current state in a variable.
Default ActiveRecord implementation uses a 'workflow_state' database column.
# File lib/workflow.rb, line 241 def load_workflow_state @workflow_state if instance_variable_defined? :@workflow_state end
persist_workflow_state(new_value)
click to toggle source
# File lib/workflow.rb, line 245 def persist_workflow_state(new_value) @workflow_state = new_value end
run_action(action, *args)
click to toggle source
# File lib/workflow.rb, line 195 def run_action(action, *args) instance_exec(*args, &action) if action end
run_action_callback(action_name, *args)
click to toggle source
# File lib/workflow.rb, line 209 def run_action_callback(action_name, *args) action = action_name.to_sym self.send(action, *args) if has_callback?(action) end
run_after_transition(from, to, event, *args)
click to toggle source
# File lib/workflow.rb, line 190 def run_after_transition(from, to, event, *args) instance_exec(from.name, to.name, event, *args, &spec.after_transition_proc) if spec.after_transition_proc end
run_before_transition(from, to, event, *args)
click to toggle source
# File lib/workflow.rb, line 172 def run_before_transition(from, to, event, *args) instance_exec(from.name, to.name, event, *args, &spec.before_transition_proc) if spec.before_transition_proc end
run_on_entry(state, prior_state, triggering_event, *args)
click to toggle source
# File lib/workflow.rb, line 214 def run_on_entry(state, prior_state, triggering_event, *args) if state.on_entry instance_exec(prior_state.name, triggering_event, *args, &state.on_entry) else hook_name = "on_#{state}_entry" self.send hook_name, prior_state, triggering_event, *args if has_callback?(hook_name) end end
run_on_error(error, from, to, event, *args)
click to toggle source
# File lib/workflow.rb, line 177 def run_on_error(error, from, to, event, *args) if spec.on_error_proc instance_exec(error, from.name, to.name, event, *args, &spec.on_error_proc) halt(error.message) else raise error end end
run_on_exit(state, new_state, triggering_event, *args)
click to toggle source
# File lib/workflow.rb, line 223 def run_on_exit(state, new_state, triggering_event, *args) if state if state.on_exit instance_exec(new_state.name, triggering_event, *args, &state.on_exit) else hook_name = "on_#{state}_exit" self.send hook_name, new_state, triggering_event, *args if has_callback?(hook_name) end end end
run_on_transition(from, to, event, *args)
click to toggle source
# File lib/workflow.rb, line 186 def run_on_transition(from, to, event, *args) instance_exec(from.name, to.name, event, *args, &spec.on_transition_proc) if spec.on_transition_proc end