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,11 +0,0 @@
1
- {:en => {
2
- :activerecord => {
3
- :errors => {
4
- :messages => {
5
- :invalid => StateMachine::Machine.default_messages[:invalid],
6
- :invalid_event => StateMachine::Machine.default_messages[:invalid_event] % ['{{state}}'],
7
- :invalid_transition => StateMachine::Machine.default_messages[:invalid_transition] % ['{{event}}']
8
- }
9
- }
10
- }
11
- }}
@@ -1,41 +0,0 @@
1
- module StateMachine
2
- module Integrations #:nodoc:
3
- module ActiveRecord
4
- # Adds support for invoking callbacks on ActiveRecord observers with more
5
- # than one argument (e.g. the record *and* the state transition). By
6
- # default, ActiveRecord only supports passing the record into the
7
- # callbacks.
8
- #
9
- # For example:
10
- #
11
- # class VehicleObserver < ActiveRecord::Observer
12
- # # The default behavior: only pass in the record
13
- # def after_save(vehicle)
14
- # end
15
- #
16
- # # Custom behavior: allow the transition to be passed in as well
17
- # def after_transition(vehicle, transition)
18
- # Audit.log(vehicle, transition)
19
- # end
20
- # end
21
- module Observer
22
- def self.included(base) #:nodoc:
23
- base.class_eval do
24
- alias_method :update_without_multiple_args, :update
25
- alias_method :update, :update_with_multiple_args
26
- end
27
- end
28
-
29
- # Allows additional arguments other than the object to be passed to the
30
- # observed methods
31
- def update_with_multiple_args(observed_method, object, *args) #:nodoc:
32
- send(observed_method, object, *args) if respond_to?(observed_method)
33
- end
34
- end
35
- end
36
- end
37
- end
38
-
39
- ActiveRecord::Observer.class_eval do
40
- include StateMachine::Integrations::ActiveRecord::Observer
41
- end
@@ -1,351 +0,0 @@
1
- module StateMachine
2
- module Integrations #:nodoc:
3
- # Adds support for integrating state machines with DataMapper resources.
4
- #
5
- # == Examples
6
- #
7
- # Below is an example of a simple state machine defined within a
8
- # DataMapper resource:
9
- #
10
- # class Vehicle
11
- # include DataMapper::Resource
12
- #
13
- # property :id, Serial
14
- # property :name, String
15
- # property :state, String
16
- #
17
- # state_machine :initial => :parked do
18
- # event :ignite do
19
- # transition :parked => :idling
20
- # end
21
- # end
22
- # end
23
- #
24
- # The examples in the sections below will use the above class as a
25
- # reference.
26
- #
27
- # == Actions
28
- #
29
- # By default, the action that will be invoked when a state is transitioned
30
- # is the +save+ action. This will cause the resource to save the changes
31
- # made to the state machine's attribute. *Note* that if any other changes
32
- # were made to the resource prior to transition, then those changes will
33
- # be saved as well.
34
- #
35
- # For example,
36
- #
37
- # vehicle = Vehicle.create # => #<Vehicle id=1 name=nil state="parked">
38
- # vehicle.name = 'Ford Explorer'
39
- # vehicle.ignite # => true
40
- # vehicle.reload # => #<Vehicle id=1 name="Ford Explorer" state="idling">
41
- #
42
- # == Events
43
- #
44
- # As described in StateMachine::InstanceMethods#state_machine, event
45
- # attributes are created for every machine that allow transitions to be
46
- # performed automatically when the object's action (in this case, :save)
47
- # is called.
48
- #
49
- # In DataMapper, these automated events are run in the following order:
50
- # * before validation - If validation feature loaded, run before callbacks and persist new states, then validate
51
- # * before save - If validation feature was skipped/not loaded, run before callbacks and persist new states, then save
52
- # * after save - Run after callbacks
53
- #
54
- # For example,
55
- #
56
- # vehicle = Vehicle.create # => #<Vehicle id=1 name=nil state="parked">
57
- # vehicle.state_event # => nil
58
- # vehicle.state_event = 'invalid'
59
- # vehicle.valid? # => false
60
- # vehicle.errors # => #<DataMapper::Validate::ValidationErrors:0xb7a48b54 @errors={"state_event"=>["is invalid"]}>
61
- #
62
- # vehicle.state_event = 'ignite'
63
- # vehicle.valid? # => true
64
- # vehicle.save # => true
65
- # vehicle.state # => "idling"
66
- # vehicle.state_event # => nil
67
- #
68
- # Note that this can also be done on a mass-assignment basis:
69
- #
70
- # vehicle = Vehicle.create(:state_event => 'ignite') # => #<Vehicle id=1 name=nil state="idling">
71
- # vehicle.state # => "idling"
72
- #
73
- # === Security implications
74
- #
75
- # Beware that public event attributes mean that events can be fired
76
- # whenever mass-assignment is being used. If you want to prevent malicious
77
- # users from tampering with events through URLs / forms, the attribute
78
- # should be protected like so:
79
- #
80
- # class Vehicle
81
- # include DataMapper::Resource
82
- # ...
83
- #
84
- # state_machine do
85
- # ...
86
- # end
87
- # protected :state_event
88
- # end
89
- #
90
- # If you want to only have *some* events be able to fire via mass-assignment,
91
- # you can build two state machines (one public and one protected) like so:
92
- #
93
- # class Vehicle
94
- # include DataMapper::Resource
95
- # ...
96
- #
97
- # state_machine do
98
- # # Define private events here
99
- # end
100
- # protected :state_event= # Prevent access to events in the first machine
101
- #
102
- # # Allow both machines to share the same state
103
- # state_machine :public_state, :attribute => :state do
104
- # # Define public events here
105
- # end
106
- # end
107
- #
108
- # == Transactions
109
- #
110
- # By default, the use of transactions during an event transition is
111
- # turned off to be consistent with DataMapper. This means that if
112
- # changes are made to the database during a before callback, but the
113
- # transition fails to complete, those changes will *not* be rolled back.
114
- #
115
- # For example,
116
- #
117
- # class Message
118
- # include DataMapper::Resource
119
- #
120
- # property :id, Serial
121
- # property :content, String
122
- # end
123
- #
124
- # Vehicle.state_machine do
125
- # before_transition do |transition|
126
- # Message.create(:content => transition.inspect)
127
- # throw :halt
128
- # end
129
- # end
130
- #
131
- # vehicle = Vehicle.create # => #<Vehicle id=1 name=nil state="parked">
132
- # vehicle.ignite # => false
133
- # Message.all.count # => 1
134
- #
135
- # To turn on transactions:
136
- #
137
- # class Vehicle < ActiveRecord::Base
138
- # state_machine :initial => :parked, :use_transactions => true do
139
- # ...
140
- # end
141
- # end
142
- #
143
- # == Validation errors
144
- #
145
- # If an event fails to successfully fire because there are no matching
146
- # transitions for the current record, a validation error is added to the
147
- # record's state attribute to help in determining why it failed and for
148
- # reporting via the UI.
149
- #
150
- # For example,
151
- #
152
- # vehicle = Vehicle.create(:state => 'idling') # => #<Vehicle id=1 name=nil state="idling">
153
- # vehicle.ignite # => false
154
- # vehicle.errors.full_messages # => ["cannot transition via \"ignite\""]
155
- #
156
- # If an event fails to fire because of a validation error on the record and
157
- # *not* because a matching transition was not available, no error messages
158
- # will be added to the state attribute.
159
- #
160
- # == Scopes
161
- #
162
- # To assist in filtering models with specific states, a series of class
163
- # methods are defined on the model for finding records with or without a
164
- # particular set of states.
165
- #
166
- # These named scopes are the functional equivalent of the following
167
- # definitions:
168
- #
169
- # class Vehicle
170
- # include DataMapper::Resource
171
- #
172
- # property :id, Serial
173
- # property :state, String
174
- #
175
- # class << self
176
- # def with_states(*states)
177
- # all(:state => states.flatten)
178
- # end
179
- # alias_method :with_state, :with_states
180
- #
181
- # def without_states(*states)
182
- # all(:state.not => states.flatten)
183
- # end
184
- # alias_method :without_state, :without_states
185
- # end
186
- # end
187
- #
188
- # *Note*, however, that the states are converted to their stored values
189
- # before being passed into the query.
190
- #
191
- # Because of the way scopes work in DataMapper, they can be chained like
192
- # so:
193
- #
194
- # Vehicle.with_state(:parked).all(:order => [:id.desc])
195
- #
196
- # == Callbacks / Observers
197
- #
198
- # All before/after transition callbacks defined for DataMapper resources
199
- # behave in the same way that other DataMapper hooks behave. Rather than
200
- # passing in the record as an argument to the callback, the callback is
201
- # instead bound to the object and evaluated within its context.
202
- #
203
- # For example,
204
- #
205
- # class Vehicle
206
- # include DataMapper::Resource
207
- #
208
- # property :id, Serial
209
- # property :state, String
210
- #
211
- # state_machine :initial => :parked do
212
- # before_transition any => :idling do
213
- # put_on_seatbelt
214
- # end
215
- #
216
- # before_transition do |transition|
217
- # # log message
218
- # end
219
- #
220
- # event :ignite do
221
- # transition :parked => :idling
222
- # end
223
- # end
224
- #
225
- # def put_on_seatbelt
226
- # ...
227
- # end
228
- # end
229
- #
230
- # Note, also, that the transition can be accessed by simply defining
231
- # additional arguments in the callback block.
232
- #
233
- # In addition to support for DataMapper-like hooks, there is additional
234
- # support for DataMapper observers. See StateMachine::Integrations::DataMapper::Observer
235
- # for more information.
236
- module DataMapper
237
- # The default options to use for state machines using this integration
238
- class << self; attr_reader :defaults; end
239
- @defaults = {:action => :save, :use_transactions => false}
240
-
241
- # Should this integration be used for state machines in the given class?
242
- # Classes that include DataMapper::Resource will automatically use the
243
- # DataMapper integration.
244
- def self.matches?(klass)
245
- defined?(::DataMapper::Resource) && klass <= ::DataMapper::Resource
246
- end
247
-
248
- # Loads additional files specific to DataMapper
249
- def self.extended(base) #:nodoc:
250
- require 'dm-core/version' unless ::DataMapper.const_defined?('VERSION')
251
- require 'state_machine/integrations/data_mapper/observer' if ::DataMapper.const_defined?('Observer')
252
- end
253
-
254
- # Forces the change in state to be recognized regardless of whether the
255
- # state value actually changed
256
- def write(object, attribute, value)
257
- result = super
258
- if attribute == :state && owner_class.properties.detect {|property| property.name == self.attribute}
259
- if ::DataMapper::VERSION =~ /^(0\.\d\.)/ # Match anything < 0.10
260
- object.original_values[self.attribute] = "#{value}-ignored"
261
- else
262
- object.original_attributes[owner_class.properties[self.attribute]] = "#{value}-ignored"
263
- end
264
- end
265
- result
266
- end
267
-
268
- # Adds a validation error to the given object
269
- def invalidate(object, attribute, message, values = [])
270
- object.errors.add(self.attribute(attribute), generate_message(message, values)) if supports_validations?
271
- end
272
-
273
- # Resets any errors previously added when invalidating the given object
274
- def reset(object)
275
- object.errors.clear if supports_validations?
276
- end
277
-
278
- protected
279
- # Is validation support currently loaded?
280
- def supports_validations?
281
- @supports_validations ||= ::DataMapper.const_defined?('Validate')
282
- end
283
-
284
- # Defines an initialization hook into the owner class for setting the
285
- # initial state of the machine *before* any attributes are set on the
286
- # object
287
- def define_state_initializer
288
- @instance_helper_module.class_eval <<-end_eval, __FILE__, __LINE__
289
- def initialize(attributes = {}, *args)
290
- ignore = attributes ? attributes.keys : []
291
- initialize_state_machines(:dynamic => false, :ignore => ignore)
292
- super
293
- initialize_state_machines(:dynamic => true, :ignore => ignore)
294
- end
295
- end_eval
296
- end
297
-
298
- # Skips defining reader/writer methods since this is done automatically
299
- def define_state_accessor
300
- owner_class.property(attribute, String) unless owner_class.properties.detect {|property| property.name == attribute}
301
-
302
- if supports_validations?
303
- name = self.name
304
- owner_class.validates_with_block(attribute) do
305
- machine = self.class.state_machine(name)
306
- machine.states.match(self) ? true : [false, machine.generate_message(:invalid)]
307
- end
308
- end
309
- end
310
-
311
- # Adds hooks into validation for automatically firing events
312
- def define_action_helpers
313
- if super && action == :save && supports_validations?
314
- @instance_helper_module.class_eval do
315
- define_method(:valid?) do |*args|
316
- self.class.state_machines.fire_event_attributes(self, :save, false) { super(*args) }
317
- end
318
- end
319
- end
320
- end
321
-
322
- # Creates a scope for finding records *with* a particular state or
323
- # states for the attribute
324
- def create_with_scope(name)
325
- attribute = self.attribute
326
- lambda {|resource, values| resource.all(attribute => values)}
327
- end
328
-
329
- # Creates a scope for finding records *without* a particular state or
330
- # states for the attribute
331
- def create_without_scope(name)
332
- attribute = self.attribute
333
- lambda {|resource, values| resource.all(attribute.to_sym.not => values)}
334
- end
335
-
336
- # Runs a new database transaction, rolling back any changes if the
337
- # yielded block fails (i.e. returns false).
338
- def transaction(object)
339
- object.class.transaction {|t| t.rollback unless yield}
340
- end
341
-
342
- # Creates a new callback in the callback chain, always ensuring that
343
- # it's configured to bind to the object as this is the convention for
344
- # DataMapper/Extlib callbacks
345
- def add_callback(type, options, &block)
346
- options[:bind_to_object] = true
347
- super
348
- end
349
- end
350
- end
351
- end
@@ -1,139 +0,0 @@
1
- module StateMachine
2
- module Integrations #:nodoc:
3
- module DataMapper
4
- # Adds support for creating before/after transition callbacks within a
5
- # DataMapper observer. These callbacks behave very similar to
6
- # before/after hooks during save/update/destroy/etc., but with the
7
- # following modifications:
8
- # * Each callback can define a set of transition conditions (i.e. guards)
9
- # that must be met in order for the callback to get invoked.
10
- # * An additional transition parameter is available that provides
11
- # contextual information about the event (see StateMachine::Transition
12
- # for more information)
13
- #
14
- # To define a single observer for multiple state machines:
15
- #
16
- # class StateMachineObserver
17
- # include DataMapper::Observer
18
- #
19
- # observe Vehicle, Switch, Project
20
- #
21
- # after_transition do |transition|
22
- # Audit.log(self, transition)
23
- # end
24
- # end
25
- #
26
- # == Requirements
27
- #
28
- # To use this feature of the DataMapper integration, the dm-observer library
29
- # must be available. This can be installed either directly or indirectly
30
- # through dm-more. When loading DataMapper, be sure to load the dm-observer
31
- # library as well like so:
32
- #
33
- # require 'rubygems'
34
- # require 'dm-core'
35
- # require 'dm-observer'
36
- #
37
- # If dm-observer is not available, then this feature will be skipped.
38
- module Observer
39
- include MatcherHelpers
40
-
41
- # Creates a callback that will be invoked *before* a transition is
42
- # performed, so long as the given configuration options match the
43
- # transition. Each part of the transition (event, to state, from state)
44
- # must match in order for the callback to get invoked.
45
- #
46
- # See StateMachine::Machine#before_transition for more
47
- # information about the various configuration options available.
48
- #
49
- # == Examples
50
- #
51
- # class Vehicle
52
- # include DataMapper::Resource
53
- #
54
- # property :id, Serial
55
- # property :state, :String
56
- #
57
- # state_machine :initial => :parked do
58
- # event :ignite do
59
- # transition :parked => :idling
60
- # end
61
- # end
62
- # end
63
- #
64
- # class VehicleObserver
65
- # include DataMapper::Observer
66
- #
67
- # observe Vehicle
68
- #
69
- # before :save do
70
- # # log message
71
- # end
72
- #
73
- # # Target all state machines
74
- # before_transition :parked => :idling, :on => :ignite do
75
- # # put on seatbelt
76
- # end
77
- #
78
- # # Target a specific state machine
79
- # before_transition :state, any => :idling do
80
- # # put on seatbelt
81
- # end
82
- #
83
- # # Target all state machines without requirements
84
- # before_transition do |transition|
85
- # # log message
86
- # end
87
- # end
88
- #
89
- # *Note* that in each of the above +before_transition+ callbacks, the
90
- # callback is executed within the context of the object (i.e. the
91
- # Vehicle instance being transition). This means that +self+ refers
92
- # to the vehicle record within each callback block.
93
- def before_transition(*args, &block)
94
- add_transition_callback(:before, *args, &block)
95
- end
96
-
97
- # Creates a callback that will be invoked *after* a transition is
98
- # performed so long as the given configuration options match the
99
- # transition.
100
- #
101
- # See +before_transition+ for a description of the possible configurations
102
- # for defining callbacks.
103
- def after_transition(*args, &block)
104
- add_transition_callback(:after, *args, &block)
105
- end
106
-
107
- private
108
- # Adds the transition callback to a specific machine or all of the
109
- # state machines for each observed class.
110
- def add_transition_callback(type, *args, &block)
111
- if args.any? && !args.first.is_a?(Hash)
112
- # Specific machine(s) being targeted
113
- names = args
114
- args = args.last.is_a?(Hash) ? [args.pop] : []
115
- else
116
- # Target all state machines
117
- names = nil
118
- end
119
-
120
- # Add the transition callback to each class being observed
121
- observing.each do |klass|
122
- state_machines =
123
- if names
124
- names.map {|name| klass.state_machines.fetch(name)}
125
- else
126
- klass.state_machines.values
127
- end
128
-
129
- state_machines.each {|machine| machine.send("#{type}_transition", *args, &block)}
130
- end if observing
131
- end
132
- end
133
- end
134
- end
135
- end
136
-
137
- DataMapper::Observer::ClassMethods.class_eval do
138
- include StateMachine::Integrations::DataMapper::Observer
139
- end