diff --git a/CHANGELOG b/CHANGELOG index 3558b95..9898a48 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +* Add some event callbacks, #aasm_event_fired(from, to), and #aasm_event_failed(event) + Based on transition logging suggestion [Artem Vasiliev] and timestamp column suggestion [Mike Ferrier] + * Add #aasm_events_for_state and #aasm_events_for_current_state [Joao Paulo Lins] * Ensure that a state is written for a new record even if aasm_current_state or diff --git a/TODO b/TODO index a2de8f7..0b146c4 100644 --- a/TODO +++ b/TODO @@ -9,5 +9,3 @@ Cool ideas from users: * Support multiple state machines on one object (Chris Nelson) * http://justbarebones.blogspot.com/2007/11/actsasstatemachine-enhancements.html (Chetan Patil) -* transition logging (Artem Vasiliev) -* timestamp column for state change on AR (Mike Ferrier) diff --git a/lib/aasm.rb b/lib/aasm.rb index 004961f..9a2f6ef 100644 --- a/lib/aasm.rb +++ b/lib/aasm.rb @@ -41,9 +41,17 @@ module AASM define_method("#{name.to_s}!") do new_state = self.class.aasm_events[name].fire(self) unless new_state.nil? + if self.respond_to?(:aasm_event_fired) + self.aasm_event_fired(self.aasm_current_state, new_state) + end + self.aasm_current_state = new_state true else + if self.respond_to?(:aasm_event_failed) + self.aasm_event_failed(name) + end + false end end diff --git a/spec/unit/aasm_spec.rb b/spec/unit/aasm_spec.rb index 93bd1be..b418bf5 100644 --- a/spec/unit/aasm_spec.rb +++ b/spec/unit/aasm_spec.rb @@ -9,6 +9,14 @@ class Foo aasm_event :close do transitions :to => :closed, :from => [:open] end + + aasm_event :null do + transitions :to => :closed, :from => [:open], :guard => :always_false + end + + def always_false + false + end end class Bar @@ -122,3 +130,27 @@ describe AASM, '- getting events for a state' do foo.aasm_events_for_current_state end end + +describe AASM, '- event callbacks' do + it 'should call aasm_event_fired if defined and successful' do + foo = Foo.new + def foo.aasm_event_fired(from, to) + end + + foo.should_receive(:aasm_event_fired) + + foo.close! + end + + it 'should call aasm_event_failed if defined and transition failed' do + foo = Foo.new + def foo.aasm_event_failed(event) + end + + foo.should_receive(:aasm_event_failed) + + foo.null! + end +end + +