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:
commit
439a5f99a4
|
@ -2,3 +2,4 @@ rdoc
|
|||
pkg
|
||||
coverage
|
||||
*~
|
||||
*.sw?
|
||||
|
|
38
README.rdoc
38
README.rdoc
|
@ -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
|
||||
|
||||
|
|
6
Rakefile
6
Rakefile
|
@ -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|
|
||||
|
|
|
@ -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.}
|
||||
|
||||
|
|
39
lib/aasm.rb
39
lib/aasm.rb
|
@ -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)
|
||||
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
|
||||
|
|
23
lib/event.rb
23
lib/event.rb
|
@ -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|
|
||||
|
|
|
@ -22,6 +22,8 @@ module AASM
|
|||
record.send(action)
|
||||
when Proc
|
||||
action.call(record)
|
||||
when Array
|
||||
action.each { |a| record.send(a) }
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue