@@ -25,11 +25,28 @@ def workflow(&specification)
25
25
26
26
private
27
27
28
+ # Creates the convinience methods like `my_transition!`
28
29
def assign_workflow ( specification_object )
29
- # TODO Ensure assign_workflow can be only called once
30
- #
31
- # creates the convinence methods, note: there is currently no way
32
- # to reassign different workflow, undefining created methods
30
+
31
+ # Merging two workflow specifications can **not** be done automically, so
32
+ # just make the latest specification win. Same for inheritance -
33
+ # definition in the subclass wins.
34
+ if respond_to? :inherited_workflow_spec # undefine methods defined by the old workflow_spec
35
+ inherited_workflow_spec . states . values . each do |state |
36
+ state_name = state . name
37
+ module_eval do
38
+ undef_method "#{ state_name } ?"
39
+ end
40
+
41
+ state . events . values . each do |event |
42
+ event_name = event . name
43
+ module_eval do
44
+ undef_method "#{ event_name } !" . to_sym
45
+ undef_method "can_#{ event_name } ?"
46
+ end
47
+ end
48
+ end
49
+ end
33
50
34
51
@workflow_spec = specification_object
35
52
@workflow_spec . states . values . each do |state |
@@ -230,6 +247,19 @@ def persist_workflow_state(new_value)
230
247
231
248
def self . included ( klass )
232
249
klass . send :include , InstanceMethods
250
+
251
+ # backup the parent workflow spec, making accessible through #inherited_workflow_spec
252
+ if klass . superclass . respond_to? ( :workflow_spec , true )
253
+ klass . module_eval do
254
+ # see http://stackoverflow.com/a/2495650/111995 for implementation explanation
255
+ pro = Proc . new { klass . superclass . workflow_spec }
256
+ singleton_class = class << self ; self ; end
257
+ singleton_class . send ( :define_method , :inherited_workflow_spec ) do
258
+ pro . call
259
+ end
260
+ end
261
+ end
262
+
233
263
klass . extend ClassMethods
234
264
235
265
if Object . const_defined? ( :ActiveRecord )
0 commit comments