branston 0.6.1 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (188) hide show
  1. data/README.rdoc +1 -1
  2. data/lib/branston/Gemfile +25 -0
  3. data/lib/branston/Gemfile.lock +76 -0
  4. data/lib/branston/app/controllers/application_controller.rb +1 -1
  5. data/lib/branston/app/controllers/outcomes_controller.rb +2 -0
  6. data/lib/branston/app/controllers/stories_controller.rb +82 -86
  7. data/lib/branston/app/controllers/users_controller.rb +69 -11
  8. data/lib/branston/app/helpers/iterations_helper.rb +13 -13
  9. data/lib/branston/app/models/iteration.rb +3 -1
  10. data/lib/branston/app/models/release.rb +0 -1
  11. data/lib/branston/app/models/story.rb +30 -28
  12. data/lib/branston/app/models/user.rb +46 -1
  13. data/lib/branston/app/views/layouts/_header.html.erb +8 -3
  14. data/lib/branston/app/views/layouts/user_roles.html.erb +5 -5
  15. data/lib/branston/app/views/sessions/new.html.erb +8 -14
  16. data/lib/branston/app/views/users/_admin_controls.html.erb +14 -0
  17. data/lib/branston/app/views/users/_form.html.erb +27 -0
  18. data/lib/branston/app/views/users/edit.html.erb +9 -0
  19. data/lib/branston/app/views/users/index.html.erb +14 -0
  20. data/lib/branston/app/views/users/new.html.erb +3 -22
  21. data/lib/branston/config/boot.rb +20 -0
  22. data/lib/branston/config/environment.rb +2 -7
  23. data/lib/branston/config/environments/test.rb +0 -8
  24. data/lib/branston/config/preinitializer.rb +21 -0
  25. data/lib/branston/config/routes.rb +15 -10
  26. data/lib/branston/db/development.sqlite3 +0 -0
  27. data/lib/branston/db/development_structure.sql +21 -8
  28. data/lib/branston/db/migrate/20100723161424_add_state_to_user.rb +12 -0
  29. data/lib/branston/db/migrate/20100726150322_add_activation_fields_to_user.rb +12 -0
  30. data/lib/branston/db/migrate/20100729125551_set_default_user_state_to_pending.rb +10 -0
  31. data/lib/branston/db/migrate/20100812133837_add_is_admin_property_to_user.rb +10 -0
  32. data/lib/branston/db/migrate/20100812140532_set_default_user_state_to_active.rb +10 -0
  33. data/lib/branston/db/migrate/20100812143455_add_default_admin_user.rb +17 -0
  34. data/lib/branston/db/migrate/20110408162438_remove_is_admin_property_and_add_role_instead.rb +12 -0
  35. data/lib/branston/db/pristine.sqlite3 +0 -0
  36. data/lib/branston/db/schema.rb +6 -8
  37. data/lib/branston/db/test.sqlite3 +0 -0
  38. data/lib/branston/log/development.log +1181 -433
  39. data/lib/branston/log/test.log +145306 -52026
  40. data/lib/branston/test/blueprints.rb +22 -28
  41. data/lib/branston/test/functional/iterations_controller_test.rb +149 -113
  42. data/lib/branston/test/functional/outcomes_controller_test.rb +94 -60
  43. data/lib/branston/test/functional/preconditions_controller_test.rb +101 -67
  44. data/lib/branston/test/functional/releases_controller_test.rb +85 -49
  45. data/lib/branston/test/functional/scenarios_controller_test.rb +104 -70
  46. data/lib/branston/test/functional/stories_controller_test.rb +41 -12
  47. data/lib/branston/test/functional/users_controller_test.rb +364 -43
  48. data/lib/branston/test/unit/iteration_test.rb +37 -6
  49. data/lib/branston/test/unit/outcome_test.rb +2 -2
  50. data/lib/branston/test/unit/participation_test.rb +2 -2
  51. data/lib/branston/test/unit/precondition_test.rb +3 -3
  52. data/lib/branston/test/unit/release_test.rb +4 -0
  53. data/lib/branston/test/unit/scenario_test.rb +4 -4
  54. data/lib/branston/test/unit/story_test.rb +62 -40
  55. data/lib/branston/test/unit/user_test.rb +195 -5
  56. metadata +136 -156
  57. data/lib/branston/app/controllers/user_roles_controller.rb +0 -105
  58. data/lib/branston/app/helpers/user_roles_helper.rb +0 -2
  59. data/lib/branston/app/models/user_role.rb +0 -21
  60. data/lib/branston/app/views/layouts/outcomes.html.erb +0 -17
  61. data/lib/branston/app/views/layouts/preconditions.html.erb +0 -17
  62. data/lib/branston/app/views/layouts/releases.html.erb +0 -17
  63. data/lib/branston/app/views/user_roles/edit.html.erb +0 -16
  64. data/lib/branston/app/views/user_roles/index.html.erb +0 -20
  65. data/lib/branston/app/views/user_roles/new.html.erb +0 -15
  66. data/lib/branston/app/views/user_roles/show.html.erb +0 -8
  67. data/lib/branston/coverage/app-controllers-application_controller_rb.html +0 -231
  68. data/lib/branston/coverage/app-controllers-iterations_controller_rb.html +0 -801
  69. data/lib/branston/coverage/app-controllers-outcomes_controller_rb.html +0 -759
  70. data/lib/branston/coverage/app-controllers-preconditions_controller_rb.html +0 -783
  71. data/lib/branston/coverage/app-controllers-releases_controller_rb.html +0 -705
  72. data/lib/branston/coverage/app-controllers-scenarios_controller_rb.html +0 -777
  73. data/lib/branston/coverage/app-controllers-sessions_controller_rb.html +0 -411
  74. data/lib/branston/coverage/app-controllers-stories_controller_rb.html +0 -1071
  75. data/lib/branston/coverage/app-controllers-user_roles_controller_rb.html +0 -693
  76. data/lib/branston/coverage/app-controllers-users_controller_rb.html +0 -315
  77. data/lib/branston/coverage/app-helpers-application_helper_rb.html +0 -327
  78. data/lib/branston/coverage/app-helpers-iterations_helper_rb.html +0 -363
  79. data/lib/branston/coverage/app-helpers-outcomes_helper_rb.html +0 -75
  80. data/lib/branston/coverage/app-helpers-preconditions_helper_rb.html +0 -75
  81. data/lib/branston/coverage/app-helpers-releases_helper_rb.html +0 -75
  82. data/lib/branston/coverage/app-helpers-sessions_helper_rb.html +0 -75
  83. data/lib/branston/coverage/app-helpers-stories_helper_rb.html +0 -75
  84. data/lib/branston/coverage/app-helpers-user_roles_helper_rb.html +0 -75
  85. data/lib/branston/coverage/app-models-iteration_rb.html +0 -321
  86. data/lib/branston/coverage/app-models-outcome_rb.html +0 -243
  87. data/lib/branston/coverage/app-models-participation_rb.html +0 -189
  88. data/lib/branston/coverage/app-models-precondition_rb.html +0 -243
  89. data/lib/branston/coverage/app-models-release_rb.html +0 -195
  90. data/lib/branston/coverage/app-models-scenario_rb.html +0 -231
  91. data/lib/branston/coverage/app-models-story_rb.html +0 -621
  92. data/lib/branston/coverage/app-models-user_rb.html +0 -513
  93. data/lib/branston/coverage/app-models-user_role_rb.html +0 -189
  94. data/lib/branston/coverage/index.html +0 -570
  95. data/lib/branston/coverage/jquery-1.3.2.min.js +0 -19
  96. data/lib/branston/coverage/jquery.tablesorter.min.js +0 -15
  97. data/lib/branston/coverage/lib-client_rb.html +0 -537
  98. data/lib/branston/coverage/lib-faker_extras_rb.html +0 -207
  99. data/lib/branston/coverage/lib-story_generator_rb.html +0 -873
  100. data/lib/branston/coverage/print.css +0 -12
  101. data/lib/branston/coverage/rcov.js +0 -42
  102. data/lib/branston/coverage/screen.css +0 -270
  103. data/lib/branston/db/migrate/20091127131037_create_user_roles.rb +0 -13
  104. data/lib/branston/db/migrate/20091127172950_add_story_id_to_user_role.rb +0 -10
  105. data/lib/branston/test/functional/user_roles_controller_test.rb +0 -71
  106. data/lib/branston/test/unit/helpers/user_roles_helper_test.rb +0 -4
  107. data/lib/branston/test/unit/user_role_test.rb +0 -9
  108. data/lib/branston/tmp/performance/BrowsingTest#test_homepage_process_time_flat.txt +0 -8
  109. data/lib/branston/tmp/performance/BrowsingTest#test_homepage_process_time_graph.html +0 -6718
  110. data/lib/branston/tmp/performance/BrowsingTest#test_homepage_process_time_tree.txt +0 -9942
  111. data/lib/branston/vendor/plugins/state_machine/CHANGELOG.rdoc +0 -298
  112. data/lib/branston/vendor/plugins/state_machine/LICENSE +0 -20
  113. data/lib/branston/vendor/plugins/state_machine/README.rdoc +0 -466
  114. data/lib/branston/vendor/plugins/state_machine/Rakefile +0 -98
  115. data/lib/branston/vendor/plugins/state_machine/examples/AutoShop_state.png +0 -0
  116. data/lib/branston/vendor/plugins/state_machine/examples/Car_state.png +0 -0
  117. data/lib/branston/vendor/plugins/state_machine/examples/TrafficLight_state.png +0 -0
  118. data/lib/branston/vendor/plugins/state_machine/examples/Vehicle_state.png +0 -0
  119. data/lib/branston/vendor/plugins/state_machine/examples/auto_shop.rb +0 -11
  120. data/lib/branston/vendor/plugins/state_machine/examples/car.rb +0 -19
  121. data/lib/branston/vendor/plugins/state_machine/examples/merb-rest/controller.rb +0 -51
  122. data/lib/branston/vendor/plugins/state_machine/examples/merb-rest/model.rb +0 -28
  123. data/lib/branston/vendor/plugins/state_machine/examples/merb-rest/view_edit.html.erb +0 -24
  124. data/lib/branston/vendor/plugins/state_machine/examples/merb-rest/view_index.html.erb +0 -23
  125. data/lib/branston/vendor/plugins/state_machine/examples/merb-rest/view_new.html.erb +0 -13
  126. data/lib/branston/vendor/plugins/state_machine/examples/merb-rest/view_show.html.erb +0 -17
  127. data/lib/branston/vendor/plugins/state_machine/examples/rails-rest/controller.rb +0 -43
  128. data/lib/branston/vendor/plugins/state_machine/examples/rails-rest/migration.rb +0 -11
  129. data/lib/branston/vendor/plugins/state_machine/examples/rails-rest/model.rb +0 -23
  130. data/lib/branston/vendor/plugins/state_machine/examples/rails-rest/view_edit.html.erb +0 -25
  131. data/lib/branston/vendor/plugins/state_machine/examples/rails-rest/view_index.html.erb +0 -23
  132. data/lib/branston/vendor/plugins/state_machine/examples/rails-rest/view_new.html.erb +0 -14
  133. data/lib/branston/vendor/plugins/state_machine/examples/rails-rest/view_show.html.erb +0 -17
  134. data/lib/branston/vendor/plugins/state_machine/examples/traffic_light.rb +0 -7
  135. data/lib/branston/vendor/plugins/state_machine/examples/vehicle.rb +0 -31
  136. data/lib/branston/vendor/plugins/state_machine/init.rb +0 -1
  137. data/lib/branston/vendor/plugins/state_machine/lib/state_machine.rb +0 -388
  138. data/lib/branston/vendor/plugins/state_machine/lib/state_machine/assertions.rb +0 -36
  139. data/lib/branston/vendor/plugins/state_machine/lib/state_machine/callback.rb +0 -189
  140. data/lib/branston/vendor/plugins/state_machine/lib/state_machine/condition_proxy.rb +0 -94
  141. data/lib/branston/vendor/plugins/state_machine/lib/state_machine/eval_helpers.rb +0 -67
  142. data/lib/branston/vendor/plugins/state_machine/lib/state_machine/event.rb +0 -252
  143. data/lib/branston/vendor/plugins/state_machine/lib/state_machine/event_collection.rb +0 -122
  144. data/lib/branston/vendor/plugins/state_machine/lib/state_machine/extensions.rb +0 -149
  145. data/lib/branston/vendor/plugins/state_machine/lib/state_machine/guard.rb +0 -230
  146. data/lib/branston/vendor/plugins/state_machine/lib/state_machine/integrations.rb +0 -68
  147. data/lib/branston/vendor/plugins/state_machine/lib/state_machine/integrations/active_record.rb +0 -492
  148. data/lib/branston/vendor/plugins/state_machine/lib/state_machine/integrations/active_record/locale.rb +0 -11
  149. data/lib/branston/vendor/plugins/state_machine/lib/state_machine/integrations/active_record/observer.rb +0 -41
  150. data/lib/branston/vendor/plugins/state_machine/lib/state_machine/integrations/data_mapper.rb +0 -351
  151. data/lib/branston/vendor/plugins/state_machine/lib/state_machine/integrations/data_mapper/observer.rb +0 -139
  152. data/lib/branston/vendor/plugins/state_machine/lib/state_machine/integrations/sequel.rb +0 -322
  153. data/lib/branston/vendor/plugins/state_machine/lib/state_machine/machine.rb +0 -1467
  154. data/lib/branston/vendor/plugins/state_machine/lib/state_machine/machine_collection.rb +0 -155
  155. data/lib/branston/vendor/plugins/state_machine/lib/state_machine/matcher.rb +0 -123
  156. data/lib/branston/vendor/plugins/state_machine/lib/state_machine/matcher_helpers.rb +0 -54
  157. data/lib/branston/vendor/plugins/state_machine/lib/state_machine/node_collection.rb +0 -152
  158. data/lib/branston/vendor/plugins/state_machine/lib/state_machine/state.rb +0 -249
  159. data/lib/branston/vendor/plugins/state_machine/lib/state_machine/state_collection.rb +0 -112
  160. data/lib/branston/vendor/plugins/state_machine/lib/state_machine/transition.rb +0 -394
  161. data/lib/branston/vendor/plugins/state_machine/state_machine.gemspec +0 -30
  162. data/lib/branston/vendor/plugins/state_machine/tasks/state_machine.rake +0 -1
  163. data/lib/branston/vendor/plugins/state_machine/tasks/state_machine.rb +0 -30
  164. data/lib/branston/vendor/plugins/state_machine/test/classes/switch.rb +0 -11
  165. data/lib/branston/vendor/plugins/state_machine/test/functional/state_machine_test.rb +0 -941
  166. data/lib/branston/vendor/plugins/state_machine/test/test_helper.rb +0 -4
  167. data/lib/branston/vendor/plugins/state_machine/test/unit/assertions_test.rb +0 -40
  168. data/lib/branston/vendor/plugins/state_machine/test/unit/callback_test.rb +0 -455
  169. data/lib/branston/vendor/plugins/state_machine/test/unit/condition_proxy_test.rb +0 -328
  170. data/lib/branston/vendor/plugins/state_machine/test/unit/eval_helpers_test.rb +0 -120
  171. data/lib/branston/vendor/plugins/state_machine/test/unit/event_collection_test.rb +0 -326
  172. data/lib/branston/vendor/plugins/state_machine/test/unit/event_test.rb +0 -743
  173. data/lib/branston/vendor/plugins/state_machine/test/unit/guard_test.rb +0 -908
  174. data/lib/branston/vendor/plugins/state_machine/test/unit/integrations/active_record_test.rb +0 -1367
  175. data/lib/branston/vendor/plugins/state_machine/test/unit/integrations/data_mapper_test.rb +0 -962
  176. data/lib/branston/vendor/plugins/state_machine/test/unit/integrations/sequel_test.rb +0 -859
  177. data/lib/branston/vendor/plugins/state_machine/test/unit/integrations_test.rb +0 -42
  178. data/lib/branston/vendor/plugins/state_machine/test/unit/invalid_event_test.rb +0 -7
  179. data/lib/branston/vendor/plugins/state_machine/test/unit/invalid_transition_test.rb +0 -7
  180. data/lib/branston/vendor/plugins/state_machine/test/unit/machine_collection_test.rb +0 -938
  181. data/lib/branston/vendor/plugins/state_machine/test/unit/machine_test.rb +0 -2004
  182. data/lib/branston/vendor/plugins/state_machine/test/unit/matcher_helpers_test.rb +0 -37
  183. data/lib/branston/vendor/plugins/state_machine/test/unit/matcher_test.rb +0 -155
  184. data/lib/branston/vendor/plugins/state_machine/test/unit/node_collection_test.rb +0 -207
  185. data/lib/branston/vendor/plugins/state_machine/test/unit/state_collection_test.rb +0 -280
  186. data/lib/branston/vendor/plugins/state_machine/test/unit/state_machine_test.rb +0 -31
  187. data/lib/branston/vendor/plugins/state_machine/test/unit/state_test.rb +0 -795
  188. data/lib/branston/vendor/plugins/state_machine/test/unit/transition_test.rb +0 -1212
@@ -1,155 +0,0 @@
1
- module StateMachine
2
- # Represents a collection of state machines for a class
3
- class MachineCollection < Hash
4
- # Initializes the state of each machine in the given object. Initial
5
- # values are only set if the machine's attribute doesn't already exist
6
- # (which must mean the defaults are being skipped)
7
- def initialize_states(object, options = {})
8
- if ignore = options[:ignore]
9
- ignore.map! {|attribute| attribute.to_sym}
10
- end
11
-
12
- each_value do |machine|
13
- if (!ignore || !ignore.include?(machine.attribute)) && (!options.include?(:dynamic) || machine.dynamic_initial_state? == options[:dynamic])
14
- value = machine.read(object, :state)
15
- machine.write(object, :state, machine.initial_state(object).value) if ignore || value.nil? || value.respond_to?(:empty?) && value.empty?
16
- end
17
- end
18
- end
19
-
20
- # Runs one or more events in parallel on the given object. See
21
- # StateMachine::InstanceMethods#fire_events for more information.
22
- def fire_events(object, *events)
23
- run_action = [true, false].include?(events.last) ? events.pop : true
24
-
25
- # Generate the transitions to run for each event
26
- transitions = events.collect do |event_name|
27
- # Find the actual event being run
28
- event = nil
29
- detect do |name, machine|
30
- event = machine.events[event_name, :qualified_name]
31
- end
32
-
33
- raise InvalidEvent, "#{event_name.inspect} is an unknown state machine event" unless event
34
-
35
- # Get the transition that will be performed for the event
36
- unless transition = event.transition_for(object)
37
- machine = event.machine
38
- machine.invalidate(object, :state, :invalid_transition, [[:event, event_name]])
39
- end
40
-
41
- transition
42
- end.compact
43
-
44
- # Run the events in parallel only if valid transitions were found for
45
- # all of them
46
- if events.length == transitions.length
47
- Transition.perform_within_transaction(transitions, :action => run_action)
48
- else
49
- false
50
- end
51
- end
52
-
53
- # Runs one or more event attributes in parallel during the invocation of
54
- # an action on the given object. after_transition callbacks can be
55
- # optionally disabled if the events are being only partially fired (for
56
- # example, when validating records in ORM integrations).
57
- #
58
- # The event attributes that will be fired are based on which machines
59
- # match the action that is being invoked.
60
- #
61
- # == Examples
62
- #
63
- # class Vehicle
64
- # include DataMapper::Resource
65
- # property :id, Serial
66
- #
67
- # state_machine :initial => :parked do
68
- # event :ignite do
69
- # transition :parked => :idling
70
- # end
71
- # end
72
- #
73
- # state_machine :alarm_state, :namespace => 'alarm', :initial => :active do
74
- # event :disable do
75
- # transition all => :off
76
- # end
77
- # end
78
- # end
79
- #
80
- # With valid events:
81
- #
82
- # vehicle = Vehicle.create # => #<Vehicle id=1 state="parked" alarm_state="active">
83
- # vehicle.state_event = 'ignite'
84
- # vehicle.alarm_state_event = 'disable'
85
- #
86
- # Vehicle.state_machines.fire_event_attributes(vehicle, :save) { true }
87
- # vehicle.state # => "idling"
88
- # vehicle.state_event # => nil
89
- # vehicle.alarm_state # => "off"
90
- # vehicle.alarm_state_event # => nil
91
- #
92
- # With invalid events:
93
- #
94
- # vehicle = Vehicle.create # => #<Vehicle id=1 state="parked" alarm_state="active">
95
- # vehicle.state_event = 'park'
96
- # vehicle.alarm_state_event = 'disable'
97
- #
98
- # Vehicle.state_machines.fire_event_attributes(vehicle, :save) { true }
99
- # vehicle.state # => "parked"
100
- # vehicle.state_event # => nil
101
- # vehicle.alarm_state # => "active"
102
- # vehicle.alarm_state_event # => nil
103
- # vehicle.errors # => #<DataMapper::Validate::ValidationErrors:0xb7af9abc @errors={"state_event"=>["is invalid"]}>
104
- #
105
- # With partial firing:
106
- #
107
- # vehicle = Vehicle.create # => #<Vehicle id=1 state="parked" alarm_state="active">
108
- # vehicle.state_event = 'ignite'
109
- #
110
- # Vehicle.state_machines.fire_event_attributes(vehicle, :save, false) { true }
111
- # vehicle.state # => "idling"
112
- # vehicle.state_event # => "ignite"
113
- # vehicle.state_event_transition # => #<StateMachine::Transition attribute=:state event=:ignite from="parked" from_name=:parked to="idling" to_name=:idling>
114
- def fire_event_attributes(object, action, complete = true)
115
- # Get the transitions to fire for each applicable machine
116
- transitions = map {|name, machine| machine.action == action ? machine.events.attribute_transition_for(object, true) : nil}.compact
117
- return yield if transitions.empty?
118
-
119
- # The value generated by the yielded block (the actual action)
120
- action_value = nil
121
-
122
- # Make sure all events were valid
123
- if result = transitions.all? {|transition| transition != false}
124
- # Clear any traces of the event since transitions are available and to
125
- # prevent from being evaluated multiple times if actions are nested
126
- transitions.each do |transition|
127
- transition.machine.write(object, :event, nil)
128
- transition.machine.write(object, :event_transition, nil)
129
- end
130
-
131
- # Perform the transitions
132
- begin
133
- result = Transition.perform(transitions, :after => complete) { action_value = yield }
134
- rescue Exception
135
- # Reset the event attribute so it can be re-evaluated if attempted again
136
- transitions.each do |transition|
137
- transition.machine.write(object, :event, transition.event)
138
- end
139
-
140
- raise
141
- end
142
-
143
- transitions.each do |transition|
144
- # Revert event if failed (to allow for more attempts)
145
- transition.machine.write(object, :event, transition.event) unless result
146
-
147
- # Track transition if partial transition was successful
148
- transition.machine.write(object, :event_transition, transition) if !complete && result
149
- end
150
- end
151
-
152
- action_value.nil? ? result : action_value
153
- end
154
- end
155
- end
@@ -1,123 +0,0 @@
1
- require 'singleton'
2
-
3
- module StateMachine
4
- # Provides a general strategy pattern for determining whether a match is found
5
- # for a value. The algorithm that actually determines the match depends on
6
- # the matcher in use.
7
- class Matcher
8
- # The list of values against which queries are matched
9
- attr_reader :values
10
-
11
- # Creates a new matcher for querying against the given set of values
12
- def initialize(values = [])
13
- @values = values.is_a?(Array) ? values : [values]
14
- end
15
-
16
- # Generates a subset of values that exists in both the set of values being
17
- # filtered and the values configured for the matcher
18
- def filter(values)
19
- self.values & values
20
- end
21
- end
22
-
23
- # Matches any given value. Since there is no configuration for this type of
24
- # matcher, it must be used as a singleton.
25
- class AllMatcher < Matcher
26
- include Singleton
27
-
28
- # Generates a blacklist matcher based on the given set of values
29
- #
30
- # == Examples
31
- #
32
- # matcher = StateMachine::AllMatcher.instance - [:parked, :idling]
33
- # matcher.matches?(:parked) # => false
34
- # matcher.matches?(:first_gear) # => true
35
- def -(blacklist)
36
- BlacklistMatcher.new(blacklist)
37
- end
38
-
39
- # Always returns true
40
- def matches?(value, context = {})
41
- true
42
- end
43
-
44
- # Always returns the given set of values
45
- def filter(values)
46
- values
47
- end
48
-
49
- # A human-readable description of this matcher. Always "all".
50
- def description
51
- 'all'
52
- end
53
- end
54
-
55
- # Matches a specific set of values
56
- class WhitelistMatcher < Matcher
57
- # Checks whether the given value exists within the whitelist configured
58
- # for this matcher.
59
- #
60
- # == Examples
61
- #
62
- # matcher = StateMachine::WhitelistMatcher.new([:parked, :idling])
63
- # matcher.matches?(:parked) # => true
64
- # matcher.matches?(:first_gear) # => false
65
- def matches?(value, context = {})
66
- values.include?(value)
67
- end
68
-
69
- # A human-readable description of this matcher
70
- def description
71
- values.length == 1 ? values.first.inspect : values.inspect
72
- end
73
- end
74
-
75
- # Matches everything but a specific set of values
76
- class BlacklistMatcher < Matcher
77
- # Checks whether the given value exists outside the blacklist configured
78
- # for this matcher.
79
- #
80
- # == Examples
81
- #
82
- # matcher = StateMachine::BlacklistMatcher.new([:parked, :idling])
83
- # matcher.matches?(:parked) # => false
84
- # matcher.matches?(:first_gear) # => true
85
- def matches?(value, context = {})
86
- !values.include?(value)
87
- end
88
-
89
- # Finds all values that are *not* within the blacklist configured for this
90
- # matcher
91
- def filter(values)
92
- values - self.values
93
- end
94
-
95
- # A human-readable description of this matcher
96
- def description
97
- "all - #{values.length == 1 ? values.first.inspect : values.inspect}"
98
- end
99
- end
100
-
101
- # Matches a loopback of two values within a context. Since there is no
102
- # configuration for this type of matcher, it must be used as a singleton.
103
- class LoopbackMatcher < Matcher
104
- include Singleton
105
-
106
- # Checks whether the given value matches what the value originally was.
107
- # This value should be defined in the context.
108
- #
109
- # == Examples
110
- #
111
- # matcher = StateMachine::LoopbackMatcher.instance
112
- # matcher.matches?(:parked, :from => :parked) # => true
113
- # matcher.matches?(:parked, :from => :idling) # => false
114
- def matches?(value, context)
115
- context[:from] == value
116
- end
117
-
118
- # A human-readable description of this matcher. Always "same".
119
- def description
120
- 'same'
121
- end
122
- end
123
- end
@@ -1,54 +0,0 @@
1
- module StateMachine
2
- # Provides a set of helper methods for generating matchers
3
- module MatcherHelpers
4
- # Represents a state that matches all known states in a machine.
5
- #
6
- # == Examples
7
- #
8
- # class Vehicle
9
- # state_machine do
10
- # before_transition any => :parked, :do => lambda {...}
11
- # before_transition all - :parked => all - :idling, :do => lambda {}
12
- #
13
- # event :park
14
- # transition all => :parked
15
- # end
16
- #
17
- # event :crash
18
- # transition all - :parked => :stalled
19
- # end
20
- # end
21
- # end
22
- #
23
- # In the above example, +all+ will match the following states since they
24
- # are known:
25
- # * +parked+
26
- # * +stalled+
27
- # * +idling+
28
- def all
29
- AllMatcher.instance
30
- end
31
- alias_method :any, :all
32
-
33
- # Represents a state that matches the original +from+ state. This is useful
34
- # for defining transitions which are loopbacks.
35
- #
36
- # == Examples
37
- #
38
- # class Vehicle
39
- # state_machine do
40
- # event :ignite
41
- # transition [:idling, :first_gear] => same
42
- # end
43
- # end
44
- # end
45
- #
46
- # In the above example, +same+ will match whichever the from state is. In
47
- # the case of the +ignite+ event, it is essential the same as the following:
48
- #
49
- # transition :parked => :parked, :first_gear => :first_gear
50
- def same
51
- LoopbackMatcher.instance
52
- end
53
- end
54
- end
@@ -1,152 +0,0 @@
1
- require 'state_machine/assertions'
2
-
3
- module StateMachine
4
- # Represents a collection of nodes in a state machine, be it events or states.
5
- class NodeCollection
6
- include Enumerable
7
- include Assertions
8
-
9
- # The machine associated with the nodes
10
- attr_reader :machine
11
-
12
- # Creates a new collection of nodes for the given state machine. By default,
13
- # the collection is empty.
14
- #
15
- # Configuration options:
16
- # * <tt>:index</tt> - One or more attributes to automatically generate
17
- # hashed indices for in order to perform quick lookups. Default is to
18
- # index by the :name attribute
19
- def initialize(machine, options = {})
20
- assert_valid_keys(options, :index)
21
- options = {:index => :name}.merge(options)
22
-
23
- @machine = machine
24
- @nodes = []
25
- @indices = Array(options[:index]).inject({}) {|indices, attribute| indices[attribute] = {}; indices}
26
- @default_index = Array(options[:index]).first
27
- end
28
-
29
- # Creates a copy of this collection such that modifications don't affect
30
- # the original collection
31
- def initialize_copy(orig) #:nodoc:
32
- super
33
-
34
- nodes = @nodes
35
- @nodes = []
36
- @indices = @indices.inject({}) {|indices, (name, index)| indices[name] = {}; indices}
37
- nodes.each {|node| self << node.dup}
38
- end
39
-
40
- # Changes the current machine associated with the collection. In turn, this
41
- # will change the state machine associated with each node in the collection.
42
- def machine=(new_machine)
43
- @machine = new_machine
44
- each {|node| node.machine = new_machine}
45
- end
46
-
47
- # Gets the number of nodes in this collection
48
- def length
49
- @nodes.length
50
- end
51
-
52
- # Gets the set of unique keys for the given index
53
- def keys(index_name = @default_index)
54
- index(index_name).keys
55
- end
56
-
57
- # Adds a new node to the collection. By doing so, this will also add it to
58
- # the configured indices.
59
- def <<(node)
60
- @nodes << node
61
- @indices.each {|attribute, index| index[value(node, attribute)] = node}
62
- self
63
- end
64
-
65
- # Updates the indexed keys for the given node. If the node's attribute
66
- # has changed since it was added to the collection, the old indexed keys
67
- # will be replaced with the updated ones.
68
- def update(node)
69
- @indices.each do |attribute, index|
70
- old_key = RUBY_VERSION < '1.9' ? index.index(node) : index.key(node)
71
- new_key = value(node, attribute)
72
-
73
- # Only replace the key if it's changed
74
- if old_key != new_key
75
- index.delete(old_key)
76
- index[new_key] = node
77
- end
78
- end
79
- end
80
-
81
- # Calls the block once for each element in self, passing that element as a
82
- # parameter.
83
- #
84
- # states = StateMachine::NodeCollection.new
85
- # states << StateMachine::State.new(machine, :parked)
86
- # states << StateMachine::State.new(machine, :idling)
87
- # states.each {|state| puts state.name, ' -- '}
88
- #
89
- # ...produces:
90
- #
91
- # parked -- idling --
92
- def each
93
- @nodes.each {|node| yield node}
94
- self
95
- end
96
-
97
- # Gets the node at the given index.
98
- #
99
- # states = StateMachine::NodeCollection.new
100
- # states << StateMachine::State.new(machine, :parked)
101
- # states << StateMachine::State.new(machine, :idling)
102
- #
103
- # states.at(0).name # => :parked
104
- # states.at(1).name # => :idling
105
- def at(index)
106
- @nodes[index]
107
- end
108
-
109
- # Gets the node indexed by the given key. By default, this will look up the
110
- # key in the first index configured for the collection. A custom index can
111
- # be specified like so:
112
- #
113
- # collection['parked', :value]
114
- #
115
- # The above will look up the "parked" key in a hash indexed by each node's
116
- # +value+ attribute.
117
- #
118
- # If the key cannot be found, then nil will be returned.
119
- def [](key, index_name = @default_index)
120
- index(index_name)[key]
121
- end
122
-
123
- # Gets the node indexed by the given key. By default, this will look up the
124
- # key in the first index configured for the collection. A custom index can
125
- # be specified like so:
126
- #
127
- # collection['parked', :value]
128
- #
129
- # The above will look up the "parked" key in a hash indexed by each node's
130
- # +value+ attribute.
131
- #
132
- # If the key cannot be found, then an IndexError exception will be raised:
133
- #
134
- # collection['invalid', :value] # => IndexError: "invalid" is an invalid value
135
- def fetch(key, index_name = @default_index)
136
- self[key, index_name] || raise(IndexError, "#{key.inspect} is an invalid #{index_name}")
137
- end
138
-
139
- private
140
- # Gets the given index. If the index does not exist, then an ArgumentError
141
- # is raised.
142
- def index(name)
143
- raise ArgumentError, 'No indices configured' unless @indices.any?
144
- @indices[name] || raise(ArgumentError, "Invalid index: #{name.inspect}")
145
- end
146
-
147
- # Gets the value for the given attribute on the node
148
- def value(node, attribute)
149
- node.send(attribute)
150
- end
151
- end
152
- end