aasm 4.2.0 → 4.3.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.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -1
  3. data/Gemfile +2 -2
  4. data/PLANNED_CHANGES.md +24 -4
  5. data/README.md +75 -5
  6. data/lib/aasm/aasm.rb +50 -36
  7. data/lib/aasm/base.rb +36 -18
  8. data/lib/aasm/core/event.rb +6 -5
  9. data/lib/aasm/core/state.rb +3 -2
  10. data/lib/aasm/core/transition.rb +5 -4
  11. data/lib/aasm/errors.rb +7 -4
  12. data/lib/aasm/instance_base.rb +14 -13
  13. data/lib/aasm/localizer.rb +1 -1
  14. data/lib/aasm/persistence/active_record_persistence.rb +41 -66
  15. data/lib/aasm/persistence/base.rb +7 -7
  16. data/lib/aasm/persistence/mongo_mapper_persistence.rb +34 -51
  17. data/lib/aasm/persistence/mongoid_persistence.rb +15 -36
  18. data/lib/aasm/persistence/plain_persistence.rb +8 -7
  19. data/lib/aasm/persistence/sequel_persistence.rb +12 -10
  20. data/lib/aasm/state_machine.rb +11 -6
  21. data/lib/aasm/version.rb +1 -1
  22. data/spec/database.rb +27 -1
  23. data/spec/models/active_record/basic_active_record_two_state_machines_example.rb +25 -0
  24. data/spec/models/active_record/complex_active_record_example.rb +33 -0
  25. data/spec/models/active_record/derivate_new_dsl.rb +4 -0
  26. data/spec/models/active_record/false_state.rb +18 -0
  27. data/spec/models/active_record/gate.rb +20 -0
  28. data/spec/models/active_record/no_direct_assignment.rb +11 -0
  29. data/spec/models/active_record/no_scope.rb +11 -0
  30. data/spec/models/active_record/provided_and_persisted_state.rb +3 -3
  31. data/spec/models/active_record/simple_new_dsl.rb +9 -0
  32. data/spec/models/active_record/thief.rb +15 -0
  33. data/spec/models/active_record/with_enum.rb +20 -0
  34. data/spec/models/active_record/with_false_enum.rb +16 -0
  35. data/spec/models/active_record/with_true_enum.rb +20 -0
  36. data/spec/models/basic_two_state_machines_example.rb +25 -0
  37. data/spec/models/callbacks/basic_multiple.rb +75 -0
  38. data/spec/models/callbacks/guard_within_block_multiple.rb +66 -0
  39. data/spec/models/callbacks/multiple_transitions_transition_guard_multiple.rb +65 -0
  40. data/spec/models/callbacks/private_method_multiple.rb +44 -0
  41. data/spec/models/callbacks/with_args_multiple.rb +61 -0
  42. data/spec/models/callbacks/{with_state_args.rb → with_state_arg.rb} +0 -0
  43. data/spec/models/callbacks/with_state_arg_multiple.rb +26 -0
  44. data/spec/models/complex_example.rb +134 -0
  45. data/spec/models/conversation.rb +47 -1
  46. data/spec/models/foo.rb +57 -0
  47. data/spec/models/foo_callback_multiple.rb +45 -0
  48. data/spec/models/guardian_multiple.rb +48 -0
  49. data/spec/models/initial_state_proc.rb +16 -0
  50. data/spec/models/invalid_persistor.rb +15 -0
  51. data/spec/models/mongo_mapper/complex_mongo_mapper_example.rb +37 -0
  52. data/spec/models/mongo_mapper/no_scope_mongo_mapper.rb +11 -0
  53. data/spec/models/mongo_mapper/simple_mongo_mapper.rb +12 -0
  54. data/spec/models/mongo_mapper/simple_new_dsl_mongo_mapper.rb +13 -0
  55. data/spec/models/mongoid/complex_mongoid_example.rb +37 -0
  56. data/spec/models/mongoid/no_scope_mongoid.rb +11 -0
  57. data/spec/models/mongoid/simple_mongoid.rb +12 -0
  58. data/spec/models/mongoid/simple_new_dsl_mongoid.rb +13 -0
  59. data/spec/models/no_initial_state.rb +13 -0
  60. data/spec/models/parametrised_event.rb +1 -1
  61. data/spec/models/parametrised_event_multiple.rb +29 -0
  62. data/spec/models/provided_state.rb +3 -3
  63. data/spec/models/sequel/complex_sequel_example.rb +45 -0
  64. data/spec/models/sequel/sequel_multiple.rb +25 -0
  65. data/spec/models/sequel/sequel_simple.rb +25 -0
  66. data/spec/models/simple_multiple_example.rb +30 -0
  67. data/spec/models/sub_class.rb +4 -0
  68. data/spec/models/sub_class_with_more_states.rb +11 -0
  69. data/spec/models/super_class.rb +28 -0
  70. data/spec/models/transactor.rb +27 -0
  71. data/spec/models/valid_state_name.rb +12 -0
  72. data/spec/models/validator.rb +39 -0
  73. data/spec/unit/basic_two_state_machines_example_spec.rb +10 -0
  74. data/spec/unit/callback_multiple_spec.rb +295 -0
  75. data/spec/unit/callbacks_spec.rb +1 -1
  76. data/spec/unit/complex_multiple_example_spec.rb +99 -0
  77. data/spec/unit/edge_cases_spec.rb +16 -0
  78. data/spec/unit/event_multiple_spec.rb +73 -0
  79. data/spec/unit/event_spec.rb +11 -6
  80. data/spec/unit/guard_multiple_spec.rb +60 -0
  81. data/spec/unit/initial_state_multiple_spec.rb +15 -0
  82. data/spec/unit/inspection_multiple_spec.rb +201 -0
  83. data/spec/unit/persistence/active_record_persistence_multiple_spec.rb +560 -0
  84. data/spec/unit/persistence/active_record_persistence_spec.rb +17 -12
  85. data/spec/unit/persistence/mongo_mapper_persistence_multiple_spec.rb +146 -0
  86. data/spec/unit/persistence/{mongo_mapper_persistance_spec.rb → mongo_mapper_persistence_spec.rb} +7 -49
  87. data/spec/unit/persistence/mongoid_persistence_multiple_spec.rb +127 -0
  88. data/spec/unit/persistence/mongoid_persistence_spec.rb +79 -0
  89. data/spec/unit/persistence/sequel_persistence_multiple_spec.rb +153 -0
  90. data/spec/unit/persistence/sequel_persistence_spec.rb +7 -24
  91. data/spec/unit/reloading_spec.rb +1 -1
  92. data/spec/unit/simple_multiple_example_spec.rb +63 -0
  93. data/spec/unit/state_spec.rb +3 -1
  94. data/spec/unit/subclassing_multiple_spec.rb +39 -0
  95. data/spec/unit/transition_spec.rb +31 -22
  96. metadata +73 -9
  97. data/spec/unit/persistence/mongoid_persistance_spec.rb +0 -146
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cd80c470206244734a77fe540848e299e87dab9f
4
- data.tar.gz: 28b464e9012345a46ddc5595d29541d52a358bf4
3
+ metadata.gz: 1b51607dcaee12f000a23ee83033925bf03dcee7
4
+ data.tar.gz: c367dd718de8264432f332ff626fc8aff05581e3
5
5
  SHA512:
6
- metadata.gz: 46d54cc3e2e66387916f7f1edfe03f3de9cb09578a8b485ea084bd68ba854f9003d1fd00de18a6d7c40984a0b0d2fe1b2d7bc4b3610e7d421c724e2f5af7a9f1
7
- data.tar.gz: cb2506c237a22fc3dc04869791d15f85614ac33096ccff60fa5a6dd40830d2325375ed13cdc3abf2adc02c958a336362027393c6ee0351bc463cf47cb0b9020f
6
+ metadata.gz: 4a3750ab5b7758679ed9ca66fc35f04cf69347a09bc03070fd514ccbd3c111f129f907e6c4e387cf253441daf7e8e79a1045ea64da43296803434711c56a2b84
7
+ data.tar.gz: d82ff5d11b0ebae4112277283706e3bd9774517e6f4a7bece806360deda054c811ccebccfefd59c05244dd05e5351f21672932ba8071a8c2626077ba76bc585d
@@ -1,6 +1,9 @@
1
1
  # CHANGELOG
2
2
 
3
- ## 4.3.0 (not yet released)
3
+ ## 4.3.0
4
+
5
+ * add support for multiple state machines per class (see [issue #158](https://github.com/aasm/aasm/issues/158) and [issue #240](https://github.com/aasm/aasm/issues/240) for details)
6
+ * special thanks to [@evadne](https://github.com/evadne) for testing this feature, and providing comments and patches (see [issue #245](https://github.com/aasm/aasm/issues/245) for details)
4
7
 
5
8
  ## 4.2.0
6
9
 
data/Gemfile CHANGED
@@ -9,7 +9,7 @@ gem 'mongoid', '~>4.0' if Gem::Version.create(RUBY_VERSION.dup) >= Gem::Version.
9
9
  gem 'sequel'
10
10
  # Since mongoid V4 requires incompatible bson V2, cannot have mongoid (V4 or greater)
11
11
  # and mongo_mapper ( or mongo ) in the same application
12
- #gem 'mongo_mapper', '~> 0.13'
13
- #gem 'bson_ext', :platforms => :ruby
12
+ # gem 'mongo_mapper', '~> 0.13'
13
+ # gem 'bson_ext', :platforms => :ruby
14
14
 
15
15
  gemspec
@@ -1,7 +1,27 @@
1
- # Planned changes for AASM 4.1
1
+ # Planned changes
2
2
 
3
- * remove support for `:on_transition` callback
3
+ ## later
4
4
 
5
- # Planned changes for AASM 4.0
5
+ * drop support for aasm_column ?
6
6
 
7
- * nothing left
7
+ # Currently working on
8
+
9
+
10
+ # Changes so far
11
+
12
+ ## version 4.3
13
+
14
+ * add support for multiple state machines per class
15
+ * class- and instance-level `aasm` methods accept a state machine selector
16
+ (aka the state machine _name_)
17
+ * if no selector/name is provided, `:default` will be used
18
+ * duplicate definitions of states and events will issue warnings
19
+ * check all tests
20
+ * _ActiveRecord_
21
+ * _Mongoid_
22
+ * _MongoMapper_
23
+ * _Sequel_
24
+ * what happen's if someone accesses `aasm`, but has defined a
25
+ state machine for `aasm(:my_name)`?
26
+ * documentation
27
+ * drop support for find_in_state, count_in_state, calculate_in_state, with_state_scope
data/README.md CHANGED
@@ -99,11 +99,11 @@ class Job
99
99
  state :running
100
100
 
101
101
  event :run, :after => :notify_somebody do
102
- transitions :from => :sleeping, :to => :running, :after => Proc.new {|*args| set_process(*args) } do
103
- before do
104
- log('Preparing to run')
105
- end
102
+ before do
103
+ log('Preparing to run')
106
104
  end
105
+
106
+ transitions :from => :sleeping, :to => :running, :after => Proc.new {|*args| set_process(*args) }
107
107
  end
108
108
 
109
109
  event :sleep do
@@ -312,9 +312,79 @@ job.stage1_completed
312
312
  job.aasm.current_state # stage3
313
313
  ```
314
314
 
315
+
316
+ ### Multiple state machine per class
317
+
318
+ Multiple state machines per class are supported. Be aware though, that _AASM_ has been
319
+ built with one state machine per class in mind. Nonetheless, here's how to do it:
320
+
321
+ ```ruby
322
+ class SimpleMultipleExample
323
+ include AASM
324
+ aasm(:move) do
325
+ state :standing, :initial => true
326
+ state :walking
327
+ state :running
328
+
329
+ event :walk do
330
+ transitions :from => :standing, :to => :walking
331
+ end
332
+ event :run do
333
+ transitions :from => [:standing, :walking], :to => :running
334
+ end
335
+ event :hold do
336
+ transitions :from => [:walking, :running], :to => :standing
337
+ end
338
+ end
339
+
340
+ aasm(:work) do
341
+ state :sleeping, :initial => true
342
+ state :processing
343
+
344
+ event :start do
345
+ transitions :from => :sleeping, :to => :processing
346
+ end
347
+ event :stop do
348
+ transitions :from => :processing, :to => :sleeping
349
+ end
350
+ end
351
+ end
352
+
353
+ simple = SimpleMultipleExample.new
354
+
355
+ simple.aasm(:move).current_state
356
+ # => :standing
357
+ simple.aasm(:work).current
358
+ # => :sleeping
359
+
360
+ simple.start
361
+ simple.aasm(:move).current_state
362
+ # => :standing
363
+ simple.aasm(:work).current
364
+ # => :processing
365
+
366
+ ```
367
+
368
+ _AASM_ doesn't prohibit to define the same event in both state machines. The
369
+ latest definition "wins" and overrides previous definitions. A warning is issued:
370
+ `SimpleMultipleExample: The event name run is already used!`.
371
+
372
+ All _AASM_ class- and instance-level `aasm` methods accept a state machine selector.
373
+ So, for example, to use inspection on a class level, you have to use
374
+
375
+ ```ruby
376
+ SimpleMultipleExample.aasm(:work).states
377
+ # => [:standing, :walking, :running]
378
+ ```
379
+
380
+ *Final note*: Support for multiple state machines per class is a pretty new feature
381
+ (since version `4.3`), so please bear with us in case it doesn't as expected.
382
+
383
+
384
+
315
385
  ### ActiveRecord
316
386
 
317
- AASM comes with support for ActiveRecord and allows automatical persisting of the object's
387
+ AASM comes with support for ActiveRecord and allows automatic persisting of the object's
318
388
  state in the database.
319
389
 
320
390
  ```ruby
@@ -8,36 +8,50 @@ module AASM
8
8
 
9
9
  # do not overwrite existing state machines, which could have been created by
10
10
  # inheritance, see class method inherited
11
- AASM::StateMachine[base] ||= AASM::StateMachine.new
11
+ AASM::StateMachine[base] ||= {}
12
12
 
13
13
  AASM::Persistence.load_persistence(base)
14
14
  super
15
15
  end
16
16
 
17
17
  module ClassMethods
18
-
19
18
  # make sure inheritance (aka subclassing) works with AASM
20
19
  def inherited(base)
21
- AASM::StateMachine[base] = AASM::StateMachine[self].clone
20
+ AASM::StateMachine[base] = {}
21
+ AASM::StateMachine[self].keys.each do |state_machine_name|
22
+ AASM::StateMachine[base][state_machine_name] = AASM::StateMachine[self][state_machine_name].clone
23
+ end
22
24
  super
23
25
  end
24
26
 
25
27
  # this is the entry point for all state and event definitions
26
- def aasm(options={}, &block)
27
- @aasm ||= AASM::Base.new(self, options)
28
- @aasm.instance_eval(&block) if block # new DSL
29
- @aasm
30
- end
28
+ def aasm(*args, &block)
29
+ if args[0].is_a?(Symbol) || args[0].is_a?(String)
30
+ # using custom name
31
+ state_machine_name = args[0].to_sym
32
+ options = args[1] || {}
33
+ else
34
+ # using the default state_machine_name
35
+ state_machine_name = :default
36
+ options = args[0] || {}
37
+ end
38
+
39
+ AASM::StateMachine[self][state_machine_name] ||= AASM::StateMachine.new(state_machine_name)
31
40
 
32
- # deprecated, remove in version 4.1
33
- def aasm_human_event_name(event) # event_name?
34
- warn '[DEPRECATION] AASM: aasm_human_event_name is deprecated, use aasm.human_event_name instead'
35
- aasm.human_event_name(event)
41
+ @aasm ||= {}
42
+ @aasm[state_machine_name] ||= AASM::Base.new(self, state_machine_name, AASM::StateMachine[self][state_machine_name], options)
43
+ @aasm[state_machine_name].instance_eval(&block) if block # new DSL
44
+ @aasm[state_machine_name]
36
45
  end
37
46
  end # ClassMethods
38
47
 
39
- def aasm
40
- @aasm ||= AASM::InstanceBase.new(self)
48
+ # this is the entry point for all instance-level access to AASM
49
+ def aasm(name=:default)
50
+ unless AASM::StateMachine[self.class][name.to_sym]
51
+ raise AASM::UnknownStateMachineError.new("There is no state machine with the name '#{name}' defined in #{self.class.name}!")
52
+ end
53
+ @aasm ||= {}
54
+ @aasm[name.to_sym] ||= AASM::InstanceBase.new(self, name.to_sym)
41
55
  end
42
56
 
43
57
  private
@@ -56,72 +70,72 @@ private
56
70
  return args
57
71
  end
58
72
 
59
- def aasm_fire_event(event_name, options, *args, &block)
60
- event = self.class.aasm.state_machine.events[event_name]
73
+ def aasm_fire_event(state_machine_name, event_name, options, *args, &block)
74
+ event = self.class.aasm(state_machine_name).state_machine.events[event_name]
61
75
  begin
62
- old_state = aasm.state_object_for_name(aasm.current_state)
76
+ old_state = aasm(state_machine_name).state_object_for_name(aasm(state_machine_name).current_state)
63
77
 
64
78
  # new event before callback
65
79
  event.fire_callbacks(
66
80
  :before,
67
81
  self,
68
- *process_args(event, aasm.current_state, *args)
82
+ *process_args(event, aasm(state_machine_name).current_state, *args)
69
83
  )
70
84
 
71
85
  if may_fire_to = event.may_fire?(self, *args)
72
86
  old_state.fire_callbacks(:before_exit, self,
73
- *process_args(event, aasm.current_state, *args))
87
+ *process_args(event, aasm(state_machine_name).current_state, *args))
74
88
  old_state.fire_callbacks(:exit, self,
75
- *process_args(event, aasm.current_state, *args)) # TODO: remove for AASM 4?
89
+ *process_args(event, aasm(state_machine_name).current_state, *args))
76
90
 
77
91
  if new_state_name = event.fire(self, {:may_fire => may_fire_to}, *args)
78
- aasm_fired(event, old_state, new_state_name, options, *args, &block)
92
+ aasm_fired(state_machine_name, event, old_state, new_state_name, options, *args, &block)
79
93
  else
80
- aasm_failed(event_name, old_state)
94
+ aasm_failed(state_machine_name, event_name, old_state)
81
95
  end
82
96
  else
83
- aasm_failed(event_name, old_state)
97
+ aasm_failed(state_machine_name, event_name, old_state)
84
98
  end
85
99
  rescue StandardError => e
86
- event.fire_callbacks(:error, self, e, *process_args(event, aasm.current_state, *args)) || raise(e)
100
+ event.fire_callbacks(:error, self, e, *process_args(event, aasm(state_machine_name).current_state, *args)) || raise(e)
87
101
  end
88
102
  end
89
103
 
90
- def aasm_fired(event, old_state, new_state_name, options, *args)
104
+ def aasm_fired(state_machine_name, event, old_state, new_state_name, options, *args)
91
105
  persist = options[:persist]
92
106
 
93
- new_state = aasm.state_object_for_name(new_state_name)
107
+ new_state = aasm(state_machine_name).state_object_for_name(new_state_name)
94
108
 
95
109
  new_state.fire_callbacks(:before_enter, self,
96
- *process_args(event, aasm.current_state, *args))
110
+ *process_args(event, aasm(state_machine_name).current_state, *args))
97
111
 
98
112
  new_state.fire_callbacks(:enter, self,
99
- *process_args(event, aasm.current_state, *args)) # TODO: remove for AASM 4?
113
+ *process_args(event, aasm(state_machine_name).current_state, *args)) # TODO: remove for AASM 4?
100
114
 
101
115
  persist_successful = true
102
116
  if persist
103
- persist_successful = aasm.set_current_state_with_persistence(new_state_name)
117
+ persist_successful = aasm(state_machine_name).set_current_state_with_persistence(new_state_name)
104
118
  if persist_successful
105
119
  yield if block_given?
106
120
  event.fire_callbacks(:success, self)
107
121
  end
108
122
  else
109
- aasm.current_state = new_state_name
123
+ aasm(state_machine_name).current_state = new_state_name
110
124
  yield if block_given?
111
125
  end
112
126
 
113
127
  if persist_successful
114
128
  old_state.fire_callbacks(:after_exit, self,
115
- *process_args(event, aasm.current_state, *args))
129
+ *process_args(event, aasm(state_machine_name).current_state, *args))
116
130
  new_state.fire_callbacks(:after_enter, self,
117
- *process_args(event, aasm.current_state, *args))
131
+ *process_args(event, aasm(state_machine_name).current_state, *args))
118
132
  event.fire_callbacks(
119
133
  :after,
120
134
  self,
121
135
  *process_args(event, old_state.name, *args)
122
136
  )
123
137
 
124
- self.aasm_event_fired(event.name, old_state.name, aasm.current_state) if self.respond_to?(:aasm_event_fired)
138
+ self.aasm_event_fired(event.name, old_state.name, aasm(state_machine_name).current_state) if self.respond_to?(:aasm_event_fired)
125
139
  else
126
140
  self.aasm_event_failed(event.name, old_state.name) if self.respond_to?(:aasm_event_failed)
127
141
  end
@@ -129,13 +143,13 @@ private
129
143
  persist_successful
130
144
  end
131
145
 
132
- def aasm_failed(event_name, old_state)
146
+ def aasm_failed(state_machine_name, event_name, old_state)
133
147
  if self.respond_to?(:aasm_event_failed)
134
148
  self.aasm_event_failed(event_name, old_state.name)
135
149
  end
136
150
 
137
- if AASM::StateMachine[self.class].config.whiny_transitions
138
- raise AASM::InvalidTransition.new(self, event_name)
151
+ if AASM::StateMachine[self.class][state_machine_name].config.whiny_transitions
152
+ raise AASM::InvalidTransition.new(self, event_name, state_machine_name)
139
153
  else
140
154
  false
141
155
  end
@@ -3,10 +3,12 @@ module AASM
3
3
 
4
4
  attr_reader :state_machine
5
5
 
6
- def initialize(klass, options={}, &block)
6
+ def initialize(klass, name, state_machine, options={}, &block)
7
7
  @klass = klass
8
- @state_machine = AASM::StateMachine[@klass]
9
- @state_machine.config.column ||= (options[:column] || :aasm_state).to_sym # aasm4
8
+ @name = name
9
+ # @state_machine = @klass.aasm(@name).state_machine
10
+ @state_machine = state_machine
11
+ @state_machine.config.column ||= (options[:column] || default_column).to_sym
10
12
  # @state_machine.config.column = options[:column].to_sym if options[:column] # master
11
13
  @options = options
12
14
 
@@ -31,7 +33,7 @@ module AASM
31
33
  # and attribute is directly assigned though
32
34
  @klass.class_eval %Q(
33
35
  def #{@state_machine.config.column}=(state_name)
34
- if self.class.aasm.state_machine.config.no_direct_assignment
36
+ if self.class.aasm(:#{@name}).state_machine.config.no_direct_assignment
35
37
  raise AASM::NoDirectAssignmentError.new(
36
38
  'direct assignment of AASM column has been disabled (see AASM configuration for this class)'
37
39
  )
@@ -64,10 +66,16 @@ module AASM
64
66
  def state(name, options={})
65
67
  @state_machine.add_state(name, @klass, options)
66
68
 
67
- @klass.send(:define_method, "#{name}?") do
68
- aasm.current_state == name
69
+ if @klass.instance_methods.include?("#{name}?")
70
+ warn "#{@klass.name}: The state name #{name} is already used!"
69
71
  end
70
72
 
73
+ @klass.class_eval <<-EORUBY, __FILE__, __LINE__ + 1
74
+ def #{name}?
75
+ aasm(:#{@name}).current_state == :#{name}
76
+ end
77
+ EORUBY
78
+
71
79
  unless @klass.const_defined?("STATE_#{name.upcase}")
72
80
  @klass.const_set("STATE_#{name.upcase}", name)
73
81
  end
@@ -75,24 +83,30 @@ module AASM
75
83
 
76
84
  # define an event
77
85
  def event(name, options={}, &block)
78
- @state_machine.events[name] = AASM::Core::Event.new(name, options, &block)
86
+ @state_machine.add_event(name, options, &block)
87
+
88
+ if @klass.instance_methods.include?("may_#{name}?".to_sym)
89
+ warn "#{@klass.name}: The event name #{name} is already used!"
90
+ end
79
91
 
80
92
  # an addition over standard aasm so that, before firing an event, you can ask
81
93
  # may_event? and get back a boolean that tells you whether the guard method
82
94
  # on the transition will let this happen.
83
- @klass.send(:define_method, "may_#{name}?") do |*args|
84
- aasm.may_fire_event?(name, *args)
85
- end
95
+ @klass.class_eval <<-EORUBY, __FILE__, __LINE__ + 1
96
+ def may_#{name}?(*args)
97
+ aasm(:#{@name}).may_fire_event?(:#{name}, *args)
98
+ end
86
99
 
87
- @klass.send(:define_method, "#{name}!") do |*args, &block|
88
- aasm.current_event = "#{name}!".to_sym
89
- aasm_fire_event(name, {:persist => true}, *args, &block)
90
- end
100
+ def #{name}!(*args, &block)
101
+ aasm(:#{@name}).current_event = :#{name}!
102
+ aasm_fire_event(:#{@name}, :#{name}, {:persist => true}, *args, &block)
103
+ end
91
104
 
92
- @klass.send(:define_method, "#{name}") do |*args, &block|
93
- aasm.current_event = name.to_sym
94
- aasm_fire_event(name, {:persist => false}, *args, &block)
95
- end
105
+ def #{name}(*args, &block)
106
+ aasm(:#{@name}).current_event = :#{name}
107
+ aasm_fire_event(:#{@name}, :#{name}, {:persist => false}, *args, &block)
108
+ end
109
+ EORUBY
96
110
  end
97
111
 
98
112
  def states
@@ -122,6 +136,10 @@ module AASM
122
136
 
123
137
  private
124
138
 
139
+ def default_column
140
+ @name.to_sym == :default ? :aasm_state : @name.to_sym
141
+ end
142
+
125
143
  def configure(key, default_value)
126
144
  if @options.key?(key)
127
145
  @state_machine.config.send("#{key}=", @options[key])
@@ -2,10 +2,11 @@ module AASM::Core
2
2
  class Event
3
3
  include DslHelper
4
4
 
5
- attr_reader :name, :options
5
+ attr_reader :name, :state_machine, :options
6
6
 
7
- def initialize(name, options = {}, &block)
7
+ def initialize(name, state_machine, options = {}, &block)
8
8
  @name = name
9
+ @state_machine = state_machine
9
10
  @transitions = []
10
11
  @guards = Array(options[:guard] || options[:guards] || options[:if])
11
12
  @unless = Array(options[:unless]) #TODO: This could use a better name
@@ -61,11 +62,11 @@ module AASM::Core
61
62
  if definitions # define new transitions
62
63
  # Create a separate transition for each from-state to the given state
63
64
  Array(definitions[:from]).each do |s|
64
- @transitions << AASM::Core::Transition.new(attach_event_guards(definitions.merge(:from => s.to_sym)), &block)
65
+ @transitions << AASM::Core::Transition.new(self, attach_event_guards(definitions.merge(:from => s.to_sym)), &block)
65
66
  end
66
67
  # Create a transition if :to is specified without :from (transitions from ANY state)
67
68
  if @transitions.empty? && definitions[:to]
68
- @transitions << AASM::Core::Transition.new(attach_event_guards(definitions), &block)
69
+ @transitions << AASM::Core::Transition.new(self, attach_event_guards(definitions), &block)
69
70
  end
70
71
  end
71
72
  @transitions
@@ -89,7 +90,7 @@ module AASM::Core
89
90
  def _fire(obj, options={}, to_state=nil, *args)
90
91
  result = options[:test_only] ? false : nil
91
92
  if @transitions.map(&:from).any?
92
- transitions = @transitions.select { |t| t.from == obj.aasm.current_state }
93
+ transitions = @transitions.select { |t| t.from == obj.aasm(state_machine.name).current_state }
93
94
  return result if transitions.size == 0
94
95
  else
95
96
  transitions = @transitions