Class: StateFu::Machine
- Includes:
- HasOptions, Applicable
- Defined in:
- lib/machine.rb
Instance Attribute Summary collapse
-
#events ⇒ Object
readonly
Instance Methods.
-
#helpers ⇒ Object
readonly
Instance Methods.
-
#hooks ⇒ Object
readonly
Returns the value of attribute hooks.
-
#named_procs ⇒ Object
readonly
Instance Methods.
-
#options ⇒ Object
readonly
Instance Methods.
-
#requirement_messages ⇒ Object
readonly
Instance Methods.
-
#states ⇒ Object
readonly
Instance Methods.
-
#tools ⇒ Object
readonly
Instance Methods.
Class Method Summary collapse
-
.bind!(machine, owner, name, options = {}) ⇒ Object
make it so that a class which has included StateFu has a binding to this machine.
- .BINDINGS ⇒ Object
-
.for_class(klass, name, options = {}, &block) ⇒ Object
Class methods.
- .load_yaml(yaml) ⇒ Object
Instance Method Summary collapse
-
#apply!(&block) ⇒ Object
(also: #lathe)
merge the commands in &block with the existing machine; returns a lathe for the machine.
-
#bind!(owner, name = DEFAULT, options = {}) ⇒ Object
make it so a class which has included StateFu has a binding to this machine.
-
#deep_clone ⇒ Object
(also: #deep_copy)
Marshal, the poor man’s X-Ray photocopier.
- #empty? ⇒ Boolean
- #event_names ⇒ Object
-
#find_or_create_states_by_name(*args) ⇒ Object
given a messy bunch of symbols, find or create a list of matching States.
- #graphviz ⇒ Object
-
#helper(*modules_to_add) ⇒ Object
the modules listed here will be mixed into Binding and Transition objects for this machine.
- #helper_modules ⇒ Object
- #initial_state ⇒ Object
- #initial_state=(s) ⇒ Object
-
#initialize(options = {}, &block) ⇒ Machine
constructor
A new instance of Machine.
- #inject_helpers_into(obj) ⇒ Object
- #inject_tools_into(obj) ⇒ Object
- #inspect ⇒ Object
-
#serializable? ⇒ Boolean
TODO simplify this by adding serializable? to state & event.
- #state_names ⇒ Object
- #to_yaml ⇒ Object
-
#tool(*modules_to_add) ⇒ Object
same as helper, but for extending Lathes rather than the Bindings / Transitions.
Methods included from HasOptions
Methods included from Applicable
Constructor Details
#initialize(options = {}, &block) ⇒ Machine
Returns a new instance of Machine.
79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/machine.rb', line 79 def initialize( ={}, &block ) @states = [].extend( StateArray ) @events = [].extend( EventArray ) @helpers = [].extend( HelperArray ) @tools = [].extend( ToolArray ) @named_procs = {} @requirement_messages = {} @options = @hooks = Hooks.for( self ) apply!( &block ) if block_given? end |
Instance Attribute Details
#events ⇒ Object (readonly)
Instance Methods
77 78 79 |
# File 'lib/machine.rb', line 77 def events @events end |
#helpers ⇒ Object (readonly)
Instance Methods
77 78 79 |
# File 'lib/machine.rb', line 77 def helpers @helpers end |
#hooks ⇒ Object (readonly)
Returns the value of attribute hooks.
11 12 13 |
# File 'lib/machine.rb', line 11 def hooks @hooks end |
#named_procs ⇒ Object (readonly)
Instance Methods
77 78 79 |
# File 'lib/machine.rb', line 77 def named_procs @named_procs end |
#options ⇒ Object (readonly)
Instance Methods
77 78 79 |
# File 'lib/machine.rb', line 77 def @options end |
#requirement_messages ⇒ Object (readonly)
Instance Methods
77 78 79 |
# File 'lib/machine.rb', line 77 def @requirement_messages end |
#states ⇒ Object (readonly)
Instance Methods
77 78 79 |
# File 'lib/machine.rb', line 77 def states @states end |
#tools ⇒ Object (readonly)
Instance Methods
77 78 79 |
# File 'lib/machine.rb', line 77 def tools @tools end |
Class Method Details
.bind!(machine, owner, name, options = {}) ⇒ Object
make it so that a class which has included StateFu has a binding to this machine
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/machine.rb', line 32 def self.bind!(machine, owner, name, ={}) name = name.to_sym [:define_methods] = (name == DEFAULT) unless .symbolize_keys!.has_key?(:define_methods) [:field_name] ||= Persistence.default_field_name(name) [:singleton] = true unless owner.is_a?(Class) if [:singleton] _binding = StateFu::Binding.new machine, owner, name, # define an accessor method with the given name MethodFactory.define_singleton_method(owner, name) { _binding } if alias_name = [:alias] || [:as] MethodFactory.define_singleton_method(owner, alias_name) { _binding } end else klass = owner klass.state_fu_machines[name] = machine klass.[name] = # prepare the state machine accessor method if owner.respond_to? name raise "FIXME " + name else klass.class_eval do define_method name do state_fu name end # allow aliases to be set up, e.g. machine(:as => :status) if alias_name = [:alias] || [:as] alias_method alias_name, name end end end # prepare event / state class methods StateFu::MethodFactory.prepare_class_machine klass, machine, name, # prepare the persistence field StateFu::Persistence.prepare_field owner, [:field_name] end end |
.BINDINGS ⇒ Object
4 5 6 |
# File 'lib/machine.rb', line 4 def self.BINDINGS @@_bindings ||= {} end |
.for_class(klass, name, options = {}, &block) ⇒ Object
Class methods
17 18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/machine.rb', line 17 def self.for_class(klass, name, ={}, &block) .symbolize_keys! name = name.to_sym unless machine = klass.state_fu_machines[ name ] machine = new() end if block_given? machine.apply! &block end machine.bind! klass, name, machine end |
Instance Method Details
#apply!(&block) ⇒ Object Also known as: lathe
merge the commands in &block with the existing machine; returns a lathe for the machine.
93 94 95 |
# File 'lib/machine.rb', line 93 def apply!( &block ) StateFu::Lathe.new( self, &block ) end |
#bind!(owner, name = DEFAULT, options = {}) ⇒ Object
make it so a class which has included StateFu has a binding to this machine
132 133 134 |
# File 'lib/machine.rb', line 132 def bind!(owner, name=DEFAULT, ={}) self.class.bind!(self, owner, name, ) end |
#deep_clone ⇒ Object Also known as: deep_copy
Marshal, the poor man’s X-Ray photocopier. TODO: a version which will not break its teeth on procs
182 183 184 |
# File 'lib/machine.rb', line 182 def deep_clone Marshal::load(Marshal.dump(self)) end |
#empty? ⇒ Boolean
136 137 138 |
# File 'lib/machine.rb', line 136 def empty? states.empty? end |
#event_names ⇒ Object
161 162 163 |
# File 'lib/machine.rb', line 161 def event_names events.map(&:name) end |
#find_or_create_states_by_name(*args) ⇒ Object
given a messy bunch of symbols, find or create a list of matching States.
167 168 169 170 171 172 173 174 175 176 177 178 |
# File 'lib/machine.rb', line 167 def find_or_create_states_by_name( *args ) args = args.compact.flatten raise ArgumentError.new( args.inspect ) unless args.all? { |a| [Symbol, StateFu::State].include? a.class } args.map do |s| unless state = states[s.to_sym] # TODO clean this line up state = s.is_a?( StateFu::State ) ? s : StateFu::State.new( self, s ) self.states << state end state end end |
#graphviz ⇒ Object
191 192 193 |
# File 'lib/machine.rb', line 191 def graphviz @graphviz ||= Plotter.new(self).output end |
#helper(*modules_to_add) ⇒ Object
the modules listed here will be mixed into Binding and Transition objects for this machine. use this to define methods, references or data useful to you during transitions, event hooks, or in general use of StateFu.
They can be supplied as a string/symbol (as per rails controller helpers), or a Module.
To do this globally, just duck-punch StateFu::Machine / StateFu::Binding.
120 121 122 |
# File 'lib/machine.rb', line 120 def helper *modules_to_add modules_to_add.each { |mod| helpers << mod } end |
#helper_modules ⇒ Object
98 99 100 |
# File 'lib/machine.rb', line 98 def helper_modules helpers.modules end |
#initial_state ⇒ Object
153 154 155 |
# File 'lib/machine.rb', line 153 def initial_state() @initial_state ||= states.first end |
#initial_state=(s) ⇒ Object
140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/machine.rb', line 140 def initial_state=( s ) case s when Symbol, String, StateFu::State unless init_state = states[ s.to_sym ] init_state = StateFu::State.new( self, s.to_sym ) states << init_state end @initial_state = init_state else raise( ArgumentError, s.inspect ) end end |
#inject_helpers_into(obj) ⇒ Object
102 103 104 |
# File 'lib/machine.rb', line 102 def inject_helpers_into( obj ) helpers.inject_into( obj ) end |
#inject_tools_into(obj) ⇒ Object
106 107 108 |
# File 'lib/machine.rb', line 106 def inject_tools_into( obj ) tools.inject_into( obj ) end |
#inspect ⇒ Object
187 188 189 |
# File 'lib/machine.rb', line 187 def inspect "#<#{self.class} ##{__id__} states=#{state_names.inspect} events=#{event_names.inspect} options=#{.inspect}>" end |
#serializable? ⇒ Boolean
TODO simplify this by adding serializable? to state & event
200 201 202 |
# File 'lib/machine.rb', line 200 def serializable? named_procs.empty? && (states + events).all?(&:serializable?) end |
#state_names ⇒ Object
157 158 159 |
# File 'lib/machine.rb', line 157 def state_names states.map(&:name) end |
#to_yaml ⇒ Object
195 196 197 |
# File 'lib/machine.rb', line 195 def to_yaml StateFu::Blueprint.to_yaml(self) end |
#tool(*modules_to_add) ⇒ Object
same as helper, but for extending Lathes rather than the Bindings / Transitions. use this to extend the Lathe DSL to suit your problem domain.
126 127 128 |
# File 'lib/machine.rb', line 126 def tool *modules_to_add modules_to_add.each { |mod| tools << mod } end |