Class: StateFu::Binding
Instance Attribute Summary collapse
-
#field_name ⇒ Object
readonly
Returns the value of attribute field_name.
-
#machine ⇒ Object
(also: #workflow, #state_machine)
readonly
Returns the value of attribute machine.
-
#method_name ⇒ Object
readonly
Returns the value of attribute method_name.
-
#object ⇒ Object
(also: #o, #obj, #model, #instance)
readonly
Returns the value of attribute object.
-
#options ⇒ Object
readonly
Returns the value of attribute options.
-
#persister ⇒ Object
readonly
Returns the value of attribute persister.
-
#target ⇒ Object
readonly
Returns the value of attribute target.
-
#transitions(opts = {}) ⇒ Object
readonly
transition validation.
Instance Method Summary collapse
-
#==(other) ⇒ Object
let’s be == (and hence ===) the current_state_name as a symbol.
-
#can_transition?(event, target = nil, *args) ⇒ Boolean
event_name? [target], *args.
-
#current_state ⇒ Object
(also: #now, #state)
the current State.
-
#current_state_name ⇒ Object
(also: #name, #state_name, #to_sym)
the name, as a Symbol, of the binding’s current_state.
-
#cycle(event_or_array = nil, *args, &block) ⇒ Object
if there is one possible cyclical event, return a transition there otherwise, maybe we got an event name as an argument?.
-
#cycle!(event_or_array = nil, *args, &block) ⇒ Object
if there is a single possible cycle() transition, fire and return it otherwise raise an IllegalTransition.
-
#cycle?(event_or_array = nil, *args) ⇒ Boolean
if there is one possible cyclical event, evaluate its requirements (true/false), else nil.
-
#events ⇒ Object
(also: #events_from_current_state)
returns a list of Events which can fire from the current_state.
-
#find_transition(event, target = nil, *args) ⇒ Object
event_name [target], *args.
-
#fire_transition!(event, target = nil, *args) ⇒ Object
event_name! [target], *args.
-
#initialize(machine, object, method_name, options = {}) ⇒ Binding
constructor
the constructor should not be called manually; a binding is returned when an instance of a class with a StateFu::Machine calls:.
-
#inspect ⇒ Object
display something sensible that doesn’t take up the whole screen.
- #invalid_events(*args) ⇒ Object
-
#next!(*args, &block) ⇒ Object
(also: #next_transition!, #next_event!, #next_state!)
if there is a next_transition, create, fire & return it otherwise raise an IllegalTransition.
-
#next?(*args, &block) ⇒ Boolean
if there is a next_transition, return true / false depending on whether its requirements are met otherwise, nil.
-
#next_event(*args) ⇒ Object
if there is exactly one event which is valid with the given optional arguments, return it.
-
#next_state(*args, &block) ⇒ Object
if there is exactly one state reachable via a transition which is valid with the given optional arguments, return it.
-
#next_states ⇒ Object
all states which can be reached from the current_state.
-
#next_transition(*args, &block) ⇒ Object
if there is exactly one legal & valid transition which can be fired with the given (optional) arguments, return it.
-
#next_transition_excluding_cycles(*args, &block) ⇒ Object
as above but ignoring any transitions whose origin and target are the same.
-
#reload ⇒ Object
SPECME DOCME OR KILLME.
-
#singleton? ⇒ Boolean
TODO better name is this a binding unique to a specific instance (not bound to a class)?.
-
#teleport!(target) ⇒ Object
change the current state of the binding without any requirements or other sanity checks, or any hooks firing.
-
#transition(event_or_array, *args, &block) ⇒ Object
initializes a new Transition to the given destination, with the given *args (to be passed to requirements and hooks).
- #valid_events(*args) ⇒ Object
- #valid_next_states(*args) ⇒ Object
- #valid_transitions(*args) ⇒ Object
Constructor Details
#initialize(machine, object, method_name, options = {}) ⇒ Binding
the constructor should not be called manually; a binding is returned when an instance of a class with a StateFu::Machine calls:
instance.#state_fu (for the default machine which is called :state_fu), instance.#state_fu( :<machine_name> ) ,or instance.#<machine_name>
15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/binding.rb', line 15 def initialize( machine, object, method_name, ={} ) @machine = machine @object = object @method_name = method_name @transitions = [] @options = .symbolize_keys! @target = singleton? ? object : object.class @field_name = [:field_name] || @target.state_fu_field_names[method_name] @persister = Persistence.for( self ) # define event methods on this binding and its @object MethodFactory.new( self ).install! @machine.helpers.inject_into( self ) end |
Instance Attribute Details
#field_name ⇒ Object (readonly)
Returns the value of attribute field_name.
4 5 6 |
# File 'lib/binding.rb', line 4 def field_name @field_name end |
#machine ⇒ Object (readonly) Also known as: workflow, state_machine
Returns the value of attribute machine.
4 5 6 |
# File 'lib/binding.rb', line 4 def machine @machine end |
#method_name ⇒ Object (readonly)
Returns the value of attribute method_name.
4 5 6 |
# File 'lib/binding.rb', line 4 def method_name @method_name end |
#object ⇒ Object (readonly) Also known as: o, obj, model, instance
Returns the value of attribute object.
4 5 6 |
# File 'lib/binding.rb', line 4 def object @object end |
#options ⇒ Object (readonly)
Returns the value of attribute options.
4 5 6 |
# File 'lib/binding.rb', line 4 def @options end |
#persister ⇒ Object (readonly)
Returns the value of attribute persister.
4 5 6 |
# File 'lib/binding.rb', line 4 def persister @persister end |
#target ⇒ Object (readonly)
Returns the value of attribute target.
4 5 6 |
# File 'lib/binding.rb', line 4 def target @target end |
#transitions(opts = {}) ⇒ Object (readonly)
transition validation
113 114 115 |
# File 'lib/binding.rb', line 113 def transitions @transitions end |
Instance Method Details
#==(other) ⇒ Object
let’s be == (and hence ===) the current_state_name as a symbol. a nice little convenience.
249 250 251 252 253 254 255 |
# File 'lib/binding.rb', line 249 def == other if other.respond_to?( :to_sym ) && current_state current_state_name == other.to_sym || super( other ) else super( other ) end end |
#can_transition?(event, target = nil, *args) ⇒ Boolean
event_name? [target], *args
75 76 77 78 79 80 81 82 83 |
# File 'lib/binding.rb', line 75 def can_transition?(event, target=nil, *args) begin if t = find_transition(event, target, *args) t.valid?(*args) end rescue IllegalTransition, UnknownTarget nil end end |
#current_state ⇒ Object Also known as: now, state
the current State
43 44 45 |
# File 'lib/binding.rb', line 43 def current_state persister.current_state end |
#current_state_name ⇒ Object Also known as: name, state_name, to_sym
the name, as a Symbol, of the binding’s current_state
50 51 52 53 54 55 56 |
# File 'lib/binding.rb', line 50 def current_state_name begin current_state.name.to_sym rescue NoMethodError nil end end |
#cycle(event_or_array = nil, *args, &block) ⇒ Object
if there is one possible cyclical event, return a transition there otherwise, maybe we got an event name as an argument?
198 199 200 201 202 203 204 205 |
# File 'lib/binding.rb', line 198 def cycle(event_or_array=nil, *args, &block) if event_or_array.nil? transitions.cyclic.with(*args, &block).singular || transitions.cyclic.with(*args, &block).valid.singular else transitions.cyclic.with(*args, &block).find(event_or_array) end end |
#cycle!(event_or_array = nil, *args, &block) ⇒ Object
if there is a single possible cycle() transition, fire and return it otherwise raise an IllegalTransition
209 210 211 212 213 214 215 |
# File 'lib/binding.rb', line 209 def cycle!(event_or_array=nil, *args, &block ) returning cycle(event_or_array, *args, &block ) do |t| raise TransitionNotFound.new( self, transitions.cyclic.with(*args,&block), "Cannot cycle! unless there is exactly one cyclic event") \ if t.nil? t.fire! end end |
#cycle?(event_or_array = nil, *args) ⇒ Boolean
if there is one possible cyclical event, evaluate its requirements (true/false), else nil
219 220 221 222 223 |
# File 'lib/binding.rb', line 219 def cycle?(event_or_array=nil, *args ) if t = cycle(event_or_array, *args ) t.requirements_met? end end |
#events ⇒ Object Also known as: events_from_current_state
returns a list of Events which can fire from the current_state
96 97 98 99 100 |
# File 'lib/binding.rb', line 96 def events machine.events.select do |e| e.can_transition_from? current_state end.extend EventArray end |
#find_transition(event, target = nil, *args) ⇒ Object
event_name [target], *args
67 68 69 70 71 |
# File 'lib/binding.rb', line 67 def find_transition(event, target=nil, *args) target ||= args.last[:to].to_sym rescue nil query = transitions.for_event(event).to(target).with(*args) query.find || query.valid.singular || nil end |
#fire_transition!(event, target = nil, *args) ⇒ Object
event_name! [target], *args
87 88 89 |
# File 'lib/binding.rb', line 87 def fire_transition!(event, target=nil, *args) find_transition(event, target, *args).fire! end |
#inspect ⇒ Object
display something sensible that doesn’t take up the whole screen
237 238 239 240 241 242 243 244 245 |
# File 'lib/binding.rb', line 237 def inspect '<#' + self.class.to_s + ' ' + attrs = [[:current_state, state_name.inspect], [:object_type , @object.class], [:method_name , method_name.inspect], [:field_name , field_name.inspect], [:machine , machine.to_s]]. map {|x| x.join('=') }.join( " " ) + '>' end |
#invalid_events(*args) ⇒ Object
129 130 131 |
# File 'lib/binding.rb', line 129 def invalid_events(*args) (events - valid_events(*args)).extend StateArray end |
#next!(*args, &block) ⇒ Object Also known as: next_transition!, next_event!, next_state!
if there is a next_transition, create, fire & return it otherwise raise an IllegalTransition
172 173 174 175 176 177 178 |
# File 'lib/binding.rb', line 172 def next!( *args, &block ) if t = next_transition( *args, &block ) t.fire! else raise TransitionNotFound.new( self, valid_transitions(*args), "Exactly 1 valid transition required.") end end |
#next?(*args, &block) ⇒ Boolean
if there is a next_transition, return true / false depending on whether its requirements are met otherwise, nil
186 187 188 189 190 |
# File 'lib/binding.rb', line 186 def next?( *args, &block ) if t = next_transition( *args, &block ) t.requirements_met? end end |
#next_event(*args) ⇒ Object
if there is exactly one event which is valid with the given optional arguments, return it
166 167 168 |
# File 'lib/binding.rb', line 166 def next_event( *args ) transitions.with(*args, &block).next_event end |
#next_state(*args, &block) ⇒ Object
if there is exactly one state reachable via a transition which is valid with the given optional arguments, return it.
160 161 162 |
# File 'lib/binding.rb', line 160 def next_state(*args, &block) transitions.with(*args, &block).next_state end |
#next_states ⇒ Object
all states which can be reached from the current_state. Does not check transition requirements, etc.
105 106 107 |
# File 'lib/binding.rb', line 105 def next_states events.map(&:targets).compact.flatten.uniq.extend StateArray end |
#next_transition(*args, &block) ⇒ Object
if there is exactly one legal & valid transition which can be fired with the given (optional) arguments, return it.
149 150 151 |
# File 'lib/binding.rb', line 149 def next_transition( *args, &block ) transitions.with(*args, &block).next end |
#next_transition_excluding_cycles(*args, &block) ⇒ Object
as above but ignoring any transitions whose origin and target are the same
154 155 156 |
# File 'lib/binding.rb', line 154 def next_transition_excluding_cycles( *args, &block ) transitions.not_cyclic.with(*args, &block).next end |
#reload ⇒ Object
SPECME DOCME OR KILLME
264 265 266 267 268 269 270 |
# File 'lib/binding.rb', line 264 def reload() if persister.is_a?( Persistence::ActiveRecord ) object.reload end persister.reload self end |
#singleton? ⇒ Boolean
TODO better name is this a binding unique to a specific instance (not bound to a class)?
259 260 261 |
# File 'lib/binding.rb', line 259 def singleton? [:singleton] end |
#teleport!(target) ⇒ Object
change the current state of the binding without any requirements or other sanity checks, or any hooks firing. Useful for test / spec scenarios, and abusing the framework.
232 233 234 |
# File 'lib/binding.rb', line 232 def teleport!( target ) persister.current_state=( machine.states[target] ) end |
#transition(event_or_array, *args, &block) ⇒ Object
initializes a new Transition to the given destination, with the given *args (to be passed to requirements and hooks).
If a block is given, it yields the Transition or is executed in its evaluation context, depending on the arity of the block.
139 140 141 |
# File 'lib/binding.rb', line 139 def transition( event_or_array, *args, &block ) return transitions.with(*args, &block).find(event_or_array) end |
#valid_events(*args) ⇒ Object
125 126 127 |
# File 'lib/binding.rb', line 125 def valid_events(*args) valid_transitions(*args).events end |
#valid_next_states(*args) ⇒ Object
121 122 123 |
# File 'lib/binding.rb', line 121 def valid_next_states(*args) valid_transitions(*args).targets end |
#valid_transitions(*args) ⇒ Object
117 118 119 |
# File 'lib/binding.rb', line 117 def valid_transitions(*args) transitions.valid.with(*args) end |