Merge branch 'dunedain289/master'

Conflicts:
	aasm.gemspec
	lib/aasm.rb
	lib/event.rb

The new event transition specs don't pass. I need to look into this.
This commit is contained in:
Travis Tilley 2009-06-07 03:26:12 -04:00
commit 439a5f99a4
8 changed files with 158 additions and 28 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@ rdoc
pkg
coverage
*~
*.sw?

View File

@ -11,14 +11,35 @@ AASM has the following features:
* Events
* Transitions
== New Callbacks
The only changes I've made are creating more callbacks with slightly more obvious semantics ;).
The callback chain & order on a successful event looks like:
oldstate:exit*
event:before
__find transition, if possible__
transition:on_transition*
newstate:enter*
oldstate:before_exit
newstate:before_enter
__update state__
oldstate:after_exit
oldstate:after_enter
event:after
event:success*
obj:aasm_event_fired*
(*) marks old callbacks
Note that the old callbacks haven't been removed and still have their same semantics. All of this behavior was added without removing any old behavior.
== Download
The latest AASM can currently be pulled from the git repository on github.
* http://github.com/rubyist/aasm/tree/master
A release and a gem are forthcoming.
* http://github.com/dunedain289/aasm/tree/master
== Installation
@ -26,12 +47,12 @@ A release and a gem are forthcoming.
=== From GitHub hosted gems
% sudo gem sources -a http://gems.github.com # (you only need to do this once)
% sudo gem install rubyist-aasm
% sudo gem install dunedain289-aasm
=== Building your own gems
% rake gem
% sudo gem install pkg/aasm-2.0.1.gem
% sudo gem install pkg/aasm-2.1.gem
== Simple Example
@ -92,11 +113,10 @@ This example uses a few of the more complex features available.
= Other Stuff
Author:: Scott Barron <scott at elitists dot net>
License:: Copyright 2006, 2007, 2008 by Scott Barron.
License:: Original code Copyright 2006, 2007, 2008 by Scott Barron.
New changes Copyright 2009 by Scott Petersen.
Released under an MIT-style license. See the LICENSE file
included in the distribution.
Bugs:: http://rubyist.lighthouseapp.com/projects/13207-aasm/
GitHub:: http://github.com/rubyist/aasm/tree/master
== Warranty

View File

@ -54,9 +54,9 @@ EOF
s.extra_rdoc_files = rd.rdoc_files.reject {|fn| fn =~ /\.rb$/}.to_a
s.rdoc_options = rd.options
s.author = 'Scott Barron'
s.email = 'scott@elitists.net'
s.homepage = 'http://rubyi.st/aasm'
s.authors = ['Scott Barron', 'Scott Petersen']
s.email = 'petersen@dunedain289.com'
s.homepage = 'http://github.com/dunedain289/aasm'
end
package_task = Rake::GemPackageTask.new(spec) do |pkg|

View File

@ -2,7 +2,7 @@ PKG_FILES = ["CHANGELOG", "MIT-LICENSE", "Rakefile", "README.rdoc", "TODO", "lib
Gem::Specification.new do |s|
s.name = 'aasm'
s.version = "2.0.7.1"
s.version = "2.1.0"
s.summary = %q{State machine mixin for Ruby objects}
s.description = %q{AASM is a continuation of the acts as state machine rails plugin, built for plain Ruby objects.}

View File

@ -5,7 +5,7 @@ require File.join(File.dirname(__FILE__), 'persistence')
module AASM
def self.Version
'2.0.7.1'
'2.1.0'
end
class InvalidTransition < RuntimeError
@ -137,32 +137,47 @@ module AASM
end
def aasm_fire_event(name, persist, *args)
aasm_state_object_for_state(aasm_current_state).call_action(:exit, self)
old_state = aasm_state_object_for_state(aasm_current_state)
event = self.class.aasm_events[name]
old_state = self.aasm_current_state
new_state = self.class.aasm_events[name].fire(self, *args)
old_state.call_action(:exit, self)
unless new_state.nil?
aasm_state_object_for_state(new_state).call_action(:enter, self)
# new event before callback
event.call_action(:before, self)
new_state_name = event.fire(self, *args)
unless new_state_name.nil?
new_state = aasm_state_object_for_state(new_state_name)
# new before_ callbacks
old_state.call_action(:before_exit, self)
new_state.call_action(:before_enter, self)
new_state.call_action(:enter, self)
persist_successful = true
if persist
persist_successful = set_aasm_current_state_with_persistence(new_state)
self.class.aasm_events[name].execute_success_callback(self) if persist_successful
persist_successful = set_aasm_current_state_with_persistence(new_state_name)
event.execute_success_callback(self) if persist_successful
else
self.aasm_current_state = new_state
self.aasm_current_state = new_state_name
end
if persist_successful
self.aasm_event_fired(name, old_state, self.aasm_current_state) if self.respond_to?(:aasm_event_fired)
if persist_successful
old_state.call_action(:after_exit, self)
new_state.call_action(:after_enter, self)
event.call_action(:after, self)
self.aasm_event_fired(name, old_state.name, self.aasm_current_state) if self.respond_to?(:aasm_event_fired)
else
self.aasm_event_failed(name, old_state) if self.respond_to?(:aasm_event_failed)
self.aasm_event_failed(name, old_state.name) if self.respond_to?(:aasm_event_failed)
end
persist_successful
else
if self.respond_to?(:aasm_event_failed)
self.aasm_event_failed(name, old_state)
self.aasm_event_failed(name, old_state.name)
end
false

View File

@ -3,12 +3,13 @@ require File.join(File.dirname(__FILE__), 'state_transition')
module AASM
module SupportingClasses
class Event
attr_reader :name, :success
attr_reader :name, :success, :options
def initialize(name, options = {}, &block)
@name = name
@success = options[:success]
@transitions = []
@options = options
instance_eval(&block) if block
end
@ -32,6 +33,10 @@ module AASM
@transitions.any? { |t| t.from == state }
end
def transitions_from_state(state)
@transitions.select { |t| t.from == state }
end
def execute_success_callback(obj, success = nil)
callback = success || @success
case(callback)
@ -44,6 +49,22 @@ module AASM
end
end
def call_action(action, record)
action = @options[action]
case action
when Symbol, String
record.send(action)
when Proc
action.call(record)
when Array
action.each { |a| record.send(a) }
end
end
def all_transitions
@transitions
end
private
def transitions(trans_opts)
Array(trans_opts[:from]).each do |s|

View File

@ -22,6 +22,8 @@ module AASM
record.send(action)
when Proc
action.call(record)
when Array
action.each { |a| record.send(a) }
end
end

View File

@ -0,0 +1,71 @@
require File.join(File.dirname(__FILE__), '..', 'spec_helper')
class Foo2
include AASM
aasm_initial_state :open
aasm_state :open, :before_enter => :before_enter_open, :before_exit => :before_exit_open, :after_enter => :after_enter_open, :after_exit => :after_exit_open
aasm_state :closed, :before_enter => :before_enter_closed, :before_exit => :before_exit_closed, :after_enter => :after_enter_closed, :after_exit => :after_exit_closed
aasm_event :close, :before => :before, :after => :after do
transitions :to => :closed, :from => [:open]
end
aasm_event :open, :before => :before, :after => :after do
transitions :to => :open, :from => :closed
end
def before_enter_open
end
def before_exit_open
end
def after_enter_open
end
def after_exit_open
end
def before_enter_closed
end
def before_exit_closed
end
def after_enter_closed
end
def after_exit_closed
end
def before
end
def after
end
end
describe Foo2, '- new callbacks' do
before(:each) do
@foo = Foo2.new
end
it "should get close callbacks" do
@foo.should_receive(:before_exit_open).once.ordered # these should be before the state changes
@foo.should_receive(:before_enter_closed).once.ordered
@foo.should_receive(:before).once.ordered
@foo.should_receive(:aasm_write_state).once.ordered.and_return(true) # this is when the state changes
@foo.should_receive(:after_exit_open).once.ordered # these should be after the state changes
@foo.should_receive(:after_enter_closed).once.ordered
@foo.should_receive(:after).once.ordered
@foo.close!
end
it "should get open callbacks" do
@foo.close!
@foo.should_receive(:before_exit_closed).once.ordered # these should be before the state changes
@foo.should_receive(:before_enter_open).once.ordered
@foo.should_receive(:before).once.ordered
@foo.should_receive(:aasm_write_state).once.ordered.and_return(true) # this is when the state changes
@foo.should_receive(:after_exit_closed).once.ordered # these should be after the state changes
@foo.should_receive(:after_enter_open).once.ordered
@foo.should_receive(:after).once.ordered
@foo.open!
end
end