davidlee-state-fu 0.3.1 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.textile +124 -34
- data/Rakefile +36 -30
- data/lib/no_stdout.rb +1 -1
- data/lib/state-fu.rb +9 -8
- data/lib/state_fu/active_support_lite/array/access.rb +12 -5
- data/lib/state_fu/active_support_lite/array/conversions.rb +10 -4
- data/lib/state_fu/active_support_lite/array/extract_options.rb +5 -4
- data/lib/state_fu/active_support_lite/array/grouping.rb +7 -4
- data/lib/state_fu/active_support_lite/array/random_access.rb +4 -3
- data/lib/state_fu/active_support_lite/array/wrapper.rb +4 -3
- data/lib/state_fu/active_support_lite/array.rb +3 -1
- data/lib/state_fu/active_support_lite/blank.rb +18 -9
- data/lib/state_fu/active_support_lite/cattr_reader.rb +4 -1
- data/lib/state_fu/active_support_lite/keys.rb +8 -3
- data/lib/state_fu/active_support_lite/misc.rb +6 -4
- data/lib/state_fu/active_support_lite/module/delegation.rb +130 -0
- data/lib/state_fu/active_support_lite/module.rb +1 -0
- data/lib/state_fu/active_support_lite/object.rb +5 -2
- data/lib/state_fu/active_support_lite/string.rb +6 -1
- data/lib/state_fu/active_support_lite/symbol.rb +2 -1
- data/lib/state_fu/applicable.rb +41 -0
- data/lib/state_fu/{helper.rb → arrays.rb} +45 -121
- data/lib/state_fu/binding.rb +136 -159
- data/lib/state_fu/core_ext.rb +78 -10
- data/lib/state_fu/event.rb +112 -48
- data/lib/state_fu/exceptions.rb +80 -34
- data/lib/state_fu/executioner.rb +149 -0
- data/lib/state_fu/has_options.rb +16 -0
- data/lib/state_fu/hooks.rb +21 -16
- data/lib/state_fu/interface.rb +80 -83
- data/lib/state_fu/lathe.rb +361 -148
- data/lib/state_fu/logger.rb +122 -45
- data/lib/state_fu/machine.rb +60 -32
- data/lib/state_fu/method_factory.rb +180 -72
- data/lib/state_fu/methodical.rb +17 -0
- data/lib/state_fu/persistence/active_record.rb +6 -1
- data/lib/state_fu/persistence/attribute.rb +1 -0
- data/lib/state_fu/persistence/base.rb +8 -6
- data/lib/state_fu/persistence.rb +94 -23
- data/lib/state_fu/sprocket.rb +26 -11
- data/lib/state_fu/state.rb +8 -27
- data/lib/state_fu/transition.rb +207 -98
- data/lib/state_fu/transition_query.rb +214 -0
- data/lib/state_fu.rb +1 -0
- data/lib/tasks/spec_last.rake +46 -0
- data/lib/tasks/state_fu.rake +57 -0
- data/lib/vizier.rb +61 -61
- data/spec/custom_formatter.rb +49 -0
- data/spec/features/binding_and_transition_helper_mixin_spec.rb +2 -2
- data/spec/features/method_missing_only_once_spec.rb +28 -0
- data/spec/features/not_requirements_spec.rb +83 -46
- data/spec/features/plotter_spec.rb +97 -0
- data/spec/features/shared_log_spec.rb +7 -0
- data/spec/features/singleton_machine_spec.rb +39 -0
- data/spec/features/state_and_array_options_accessor_spec.rb +1 -1
- data/spec/features/{transition_boolean_comparison.rb → transition_boolean_comparison_spec.rb} +29 -18
- data/spec/helper.rb +6 -117
- data/spec/integration/active_record_persistence_spec.rb +18 -4
- data/spec/integration/binding_extension_spec.rb +1 -1
- data/spec/integration/class_accessor_spec.rb +49 -59
- data/spec/integration/event_definition_spec.rb +20 -20
- data/spec/integration/example_01_document_spec.rb +13 -8
- data/spec/integration/example_02_string_spec.rb +3 -2
- data/spec/integration/instance_accessor_spec.rb +16 -19
- data/spec/integration/lathe_extension_spec.rb +2 -2
- data/spec/integration/machine_duplication_spec.rb +59 -37
- data/spec/integration/relaxdb_persistence_spec.rb +6 -3
- data/spec/integration/requirement_reflection_spec.rb +66 -57
- data/spec/integration/state_definition_spec.rb +72 -66
- data/spec/integration/transition_spec.rb +169 -173
- data/spec/spec.opts +5 -3
- data/spec/spec_helper.rb +132 -0
- data/spec/state_fu_spec.rb +870 -0
- data/spec/units/binding_spec.rb +33 -22
- data/spec/units/event_spec.rb +3 -22
- data/spec/units/exceptions_spec.rb +7 -0
- data/spec/units/lathe_spec.rb +7 -7
- data/spec/units/machine_spec.rb +67 -75
- data/spec/units/method_factory_spec.rb +55 -48
- data/spec/units/sprocket_spec.rb +5 -7
- data/spec/units/state_spec.rb +33 -24
- metadata +31 -19
- data/lib/state_fu/active_support_lite/inheritable_attributes.rb +0 -1
- data/lib/state_fu/fu_space.rb +0 -51
- data/lib/state_fu/mock_transition.rb +0 -38
- data/spec/BDD/plotter_spec.rb +0 -115
- data/spec/integration/dynamic_requirement_spec.rb +0 -160
- data/spec/integration/ex_machine_for_accounts_spec.rb +0 -79
- data/spec/integration/sanity_spec.rb +0 -31
- data/spec/units/fu_space_spec.rb +0 -95
data/lib/state_fu/interface.rb
CHANGED
|
@@ -1,5 +1,39 @@
|
|
|
1
1
|
module StateFu
|
|
2
2
|
module Interface
|
|
3
|
+
module SoftAlias
|
|
4
|
+
|
|
5
|
+
# define aliases that won't clobber existing methods -
|
|
6
|
+
# so we can be liberal with them.
|
|
7
|
+
def soft_alias(x)
|
|
8
|
+
aliases = [ x.to_a[0] ].flatten
|
|
9
|
+
original = aliases.shift
|
|
10
|
+
existing_method_names = (self.instance_methods | self.protected_instance_methods | self.private_instance_methods).map(&:to_sym)
|
|
11
|
+
taken, ok = aliases.partition { |a| existing_method_names.include?(a.to_sym) }
|
|
12
|
+
StateFu::Logger.debug("#{self.to_s} alias for ## #{original} already taken: #{taken.inspect}") unless taken.empty?
|
|
13
|
+
ok.each { |a| alias_method a, original}
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
module Aliases
|
|
19
|
+
|
|
20
|
+
def self.extended(base)
|
|
21
|
+
base.extend SoftAlias
|
|
22
|
+
base.class_eval do
|
|
23
|
+
# instance method aliases
|
|
24
|
+
soft_alias :state_fu => [:stfu, :fu, :stateful, :workflow, :engine, :machine, :context]
|
|
25
|
+
soft_alias :state_fu_bindings => [:bindings, :workflows, :engines, :machines, :contexts]
|
|
26
|
+
soft_alias :state_fu! => [:stfu!, :initialize_machines!, :initialize_state!]
|
|
27
|
+
class << self
|
|
28
|
+
extend SoftAlias
|
|
29
|
+
# class method aliases
|
|
30
|
+
soft_alias :state_fu_machine => [:stfu, :state_fu, :workflow, :stateful, :statefully, :state_machine, :engine]
|
|
31
|
+
soft_alias :state_fu_machines => [:stfus, :state_fus, :workflows, :engines]
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
3
37
|
# Provides access to StateFu to your classes. Plenty of aliases are
|
|
4
38
|
# provided so you can use whatever makes sense to you.
|
|
5
39
|
module ClassMethods
|
|
@@ -12,9 +46,10 @@ module StateFu
|
|
|
12
46
|
# class, creating it if it did not exist.
|
|
13
47
|
#
|
|
14
48
|
# Given a symbol, return the machine by that name, creating it
|
|
15
|
-
# if it didn't exist.
|
|
49
|
+
# if it didn't exist, and definining it if a block is passed.
|
|
16
50
|
#
|
|
17
|
-
# Given a block,
|
|
51
|
+
# Given a block, apply it to a StateFu::Lathe to define a
|
|
52
|
+
# machine, and return it.
|
|
18
53
|
#
|
|
19
54
|
# This can be done multiple times; changes are cumulative.
|
|
20
55
|
#
|
|
@@ -24,54 +59,36 @@ module StateFu
|
|
|
24
59
|
# # equivalent to Klass.machine(:om)
|
|
25
60
|
# Klass.machine(:workflow) # another totally separate machine
|
|
26
61
|
#
|
|
27
|
-
#
|
|
28
|
-
|
|
29
|
-
|
|
62
|
+
# recognised options are:
|
|
63
|
+
# :field_name - specify the field to use for persistence.
|
|
64
|
+
# defaults to {machine_name}_field.
|
|
65
|
+
#
|
|
66
|
+
def state_fu_machine( *args, &block )
|
|
30
67
|
options = args.extract_options!.symbolize_keys!
|
|
31
|
-
name = args[0] ||
|
|
68
|
+
name = args[0] || DEFAULT
|
|
32
69
|
StateFu::Machine.for_class( self, name, options, &block )
|
|
33
70
|
end
|
|
34
|
-
alias_method :
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
alias_method :statefully, :machine
|
|
39
|
-
alias_method :state_machine, :machine
|
|
40
|
-
alias_method :engine, :machine
|
|
41
|
-
|
|
42
|
-
# return a hash of :name => StateFu::Machine for your class.
|
|
43
|
-
def machines( *args, &block )
|
|
44
|
-
if args.empty? && !block_given?
|
|
45
|
-
StateFu::FuSpace.class_machines[self]
|
|
46
|
-
else
|
|
47
|
-
machine( *args, &block)
|
|
48
|
-
end
|
|
71
|
+
alias_method :machine, :state_fu_machine
|
|
72
|
+
|
|
73
|
+
def state_fu_field_names
|
|
74
|
+
@_state_fu_field_names ||= {}
|
|
49
75
|
end
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
alias_method :engines, :machines
|
|
54
|
-
|
|
55
|
-
# return the list of machines names for this class
|
|
56
|
-
def machine_names()
|
|
57
|
-
StateFu::FuSpace.class_machines[self].keys
|
|
76
|
+
|
|
77
|
+
def state_fu_machines
|
|
78
|
+
@_state_fu_machines ||= {}
|
|
58
79
|
end
|
|
59
|
-
alias_method :
|
|
60
|
-
|
|
61
|
-
alias_method :workflow_names, :machine_names
|
|
62
|
-
alias_method :engine_names, :machine_names
|
|
80
|
+
alias_method :machines, :state_fu_machines
|
|
81
|
+
|
|
63
82
|
end
|
|
64
83
|
|
|
65
84
|
# These methods grant access to StateFu::Binding objects, which
|
|
66
85
|
# are bundles of context encapsulating a StateFu::Machine, an instance
|
|
67
86
|
# of a class, and its current state in the machine.
|
|
68
87
|
|
|
69
|
-
# Again, plenty of aliases are provided so you can use whatever
|
|
70
|
-
# makes sense to you.
|
|
71
88
|
module InstanceMethods
|
|
72
|
-
|
|
73
|
-
def
|
|
74
|
-
@
|
|
89
|
+
|
|
90
|
+
def state_fu_bindings
|
|
91
|
+
@_state_fu_bindings ||= {}
|
|
75
92
|
end
|
|
76
93
|
|
|
77
94
|
# A StateFu::Binding comes into being when it is first referenced.
|
|
@@ -79,57 +96,37 @@ module StateFu
|
|
|
79
96
|
# This is the accessor method through which an object instance (or developer)
|
|
80
97
|
# can access a StateFu::Machine, the object's current state, the
|
|
81
98
|
# methods which trigger event transitions, etc.
|
|
82
|
-
|
|
83
|
-
def
|
|
84
|
-
name = name.to_sym
|
|
85
|
-
if
|
|
86
|
-
|
|
99
|
+
|
|
100
|
+
def state_fu_binding( name = DEFAULT )
|
|
101
|
+
name = name.to_sym
|
|
102
|
+
if machine = self.class.state_fu_machines[name]
|
|
103
|
+
state_fu_bindings[name] ||= StateFu::Binding.new( machine, self, name )
|
|
104
|
+
else raise ArgumentError.new("No state machine called #{name} for #{self.class} #{self}")
|
|
87
105
|
end
|
|
88
106
|
end
|
|
107
|
+
alias_method :state_fu, :state_fu_binding
|
|
89
108
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
alias_method :machine, :_binding # not strictly accurate
|
|
97
|
-
alias_method :context, :_binding
|
|
98
|
-
|
|
99
|
-
# Gain awareness of all bindings (state contexts) this object
|
|
100
|
-
# has contemplated into being.
|
|
101
|
-
# Returns a Hash of { :name => <StateFu::Binding>, ... }
|
|
102
|
-
def _bindings()
|
|
103
|
-
_state_fu
|
|
109
|
+
def current_state( name = DEFAULT )
|
|
110
|
+
state_fu_binding(name).current_state
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def next!(name = DEFAULT, *args, &block )
|
|
114
|
+
state_fu_binding(name).next! *args, &block
|
|
104
115
|
end
|
|
116
|
+
alias_method :next_state!, :next!
|
|
117
|
+
alias_method :fire_next_transition!, :next!
|
|
105
118
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
alias_method :state_fus, :_bindings
|
|
109
|
-
alias_method :state_foos, :_bindings
|
|
110
|
-
alias_method :workflows, :_bindings
|
|
111
|
-
alias_method :engines, :_bindings
|
|
112
|
-
alias_method :bindings, :_bindings
|
|
113
|
-
alias_method :machines, :_bindings # not strictly accurate
|
|
114
|
-
alias_method :contexts, :_bindings
|
|
115
|
-
|
|
116
|
-
# Instantiate bindings for all machines defined for this class.
|
|
119
|
+
# Instantiate bindings for all machines, which ensures that persistence
|
|
120
|
+
# fields are intialized and event methods defined.
|
|
117
121
|
# It's useful to call this before_create w/
|
|
118
122
|
# ActiveRecord classes, as this will cause the database field
|
|
119
123
|
# to be populated with the default state name.
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
@state_fu_initialized = true
|
|
125
|
-
names.map { |n| _binding( n ) }
|
|
124
|
+
|
|
125
|
+
def state_fu!
|
|
126
|
+
MethodFactory.define_singleton_method(self, :initialize_state_fu!) { true }
|
|
127
|
+
self.class.state_fu_machines.keys.map { |n| state_fu_binding( n ) }
|
|
126
128
|
end
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
alias_method :initialize_state!, :state_fu!
|
|
132
|
-
alias_method :build_workflow!, :state_fu!
|
|
133
|
-
end
|
|
134
|
-
end
|
|
135
|
-
end
|
|
129
|
+
|
|
130
|
+
end # ClassMethods
|
|
131
|
+
end # Interface
|
|
132
|
+
end # StateFu
|