1
0
Fork 0
mirror of https://github.com/aasm/aasm synced 2023-03-27 23:22:41 -04:00

Merge branch 'master' into aasm4

Conflicts:
	CHANGELOG.md
	lib/aasm/event.rb
This commit is contained in:
Thorsten Böttger 2013-12-16 22:21:54 +01:00
commit 8bb01faebd
27 changed files with 215 additions and 302 deletions

View file

@ -9,6 +9,10 @@
[#80](https://github.com/aasm/aasm/issues/80) [#80](https://github.com/aasm/aasm/issues/80)
thanks to [@ejlangev](https://github.com/ejlangev)) thanks to [@ejlangev](https://github.com/ejlangev))
## 3.1.0 (not yet released)
* deprecated old aasm_* class methods (old-style DSL), in preparation for AASM v4.0.0
## 3.0.24 ## 3.0.24
* added support for event blocks (thanks to [@Intrepidd](https://github.com/Intrepidd)) * added support for event blocks (thanks to [@Intrepidd](https://github.com/Intrepidd))

View file

@ -1,4 +1,4 @@
Copyright (c) 2006-2012 Scott Barron Copyright (c) 2006-2014 Scott Barron
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the a copy of this software and associated documentation files (the

View file

@ -257,6 +257,7 @@ to include Mongoid::Document before you include AASM.
class Job class Job
include Mongoid::Document include Mongoid::Document
include AASM include AASM
field :aasm_state
aasm do aasm do
... ...
end end
@ -325,9 +326,9 @@ class Job < ActiveRecord::Base
aasm do aasm do
state :sleeping, :initial => true state :sleeping, :initial => true
state :running state :running, :after_commit => :notify_about_running_job
event :run, :after_commit => :notify_about_running_job do event :run do
transitions :from => :sleeping, :to => :running transitions :from => :sleeping, :to => :running
end end
end end
@ -417,7 +418,7 @@ gem 'aasm'
## Latest changes ## ## Latest changes ##
Look at the [CHANGELOG](https://github.com/aasm/aasm/blob/master/CHANGELOG.md) for details. Take a look at the [CHANGELOG](https://github.com/aasm/aasm/blob/master/CHANGELOG.md) for details about recent changes to the current version.
## Questions? ## ## Questions? ##
@ -427,11 +428,11 @@ Feel free to
* [ask a question on StackOverflow](http://stackoverflow.com) (tag with `aasm`) * [ask a question on StackOverflow](http://stackoverflow.com) (tag with `aasm`)
* send us a tweet [@aasm](http://twitter.com/aasm) * send us a tweet [@aasm](http://twitter.com/aasm)
## Authors ## ## Maintainers ##
* [Scott Barron](https://github.com/rubyist) * [Scott Barron](https://github.com/rubyist) (20062009, original author)
* [Travis Tilley](https://github.com/ttilley) * [Travis Tilley](https://github.com/ttilley) (20092011)
* [Thorsten Böttger](http://github.com/alto) * [Thorsten Böttger](http://github.com/alto) (since 2011)
## Warranty ## ## Warranty ##
@ -443,7 +444,7 @@ purpose.
## License ## ## License ##
Copyright (c) 2006-2012 Scott Barron Copyright (c) 2006-2014 Scott Barron
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the a copy of this software and associated documentation files (the

View file

@ -13,6 +13,3 @@ require 'ostruct'
persistence persistence
aasm aasm
).each { |file| require File.join(File.dirname(__FILE__), 'aasm', file) } ).each { |file| require File.join(File.dirname(__FILE__), 'aasm', file) }
# load the deprecated methods and modules
Dir[File.join(File.dirname(__FILE__), 'aasm', 'deprecated', '*.rb')].sort.each { |f| require File.expand_path(f) }

View file

@ -26,52 +26,56 @@ module AASM
@aasm @aasm
end end
# TODO: maybe better: aasm.initial_state # TODO remove this method in v4.0.0
def aasm_initial_state(set_state=nil) def aasm_initial_state(set_state=nil)
if set_state if set_state
# deprecated way to set the value warn ".aasm_initial_state(:name) is deprecated and will be removed in version 4.0.0; please use .aasm.initial_state = :name instead!"
AASM::StateMachine[self].initial_state = set_state AASM::StateMachine[self].initial_state = set_state
else else
warn ".aasm_initial_state is deprecated and will be removed in version 4.0.0; please use .aasm.initial_state instead!"
AASM::StateMachine[self].initial_state AASM::StateMachine[self].initial_state
end end
end end
# is this better?: aasm.states.name.from_states # TODO remove this method in v4.0.0
def aasm_from_states_for_state(state, options={}) def aasm_from_states_for_state(state, options={})
if options[:transition] warn ".aasm_from_states_for_state is deprecated and will be removed in version 4.0.0; please use .aasm.from_states_for_state instead!"
aasm.events[options[:transition]].transitions_to_state(state).flatten.map(&:from).flatten aasm.from_states_for_state(state, options)
else
aasm.events.map {|k,v| v.transitions_to_state(state)}.flatten.map(&:from).flatten
end
end end
# deprecated # TODO remove this method in v4.0.0
def aasm_initial_state=(state) def aasm_initial_state=(state)
warn ".aasm_initial_state= is deprecated and will be removed in version 4.0.0"
AASM::StateMachine[self].initial_state = state AASM::StateMachine[self].initial_state = state
end end
# deprecated # TODO remove this method in v4.0.0
def aasm_state(name, options={}) def aasm_state(name, options={})
warn ".aasm_state is deprecated and will be removed in version 4.0.0; please use .aasm.state instead!"
aasm.state(name, options) aasm.state(name, options)
end end
# deprecated # TODO remove this method in v4.0.0
def aasm_event(name, options = {}, &block) def aasm_event(name, options = {}, &block)
warn ".aasm_event is deprecated and will be removed in version 4.0.0; please use .aasm.event instead!"
aasm.event(name, options, &block) aasm.event(name, options, &block)
end end
# deprecated # TODO remove this method in v4.0.0
def aasm_states def aasm_states
warn ".aasm_states is deprecated and will be removed in version 4.0.0; please use .aasm.states instead!"
aasm.states aasm.states
end end
# deprecated # TODO remove this method in v4.0.0
def aasm_events def aasm_events
warn ".aasm_events is deprecated and will be removed in version 4.0.0; please use .aasm.events instead!"
aasm.events aasm.events
end end
# deprecated # TODO remove this method in v4.0.0
def aasm_states_for_select def aasm_states_for_select
warn ".aasm_states_for_select is deprecated and will be removed in version 4.0.0; please use .aasm.states_for_select instead!"
aasm.states_for_select aasm.states_for_select
end end
@ -103,39 +107,39 @@ module AASM
true true
end end
# deprecated # TODO remove this method in v4.0.0
def aasm_current_state def aasm_current_state
# warn "#aasm_current_state is deprecated and will be removed in version 3.2.0; please use #aasm.state instead!" warn "#aasm_current_state is deprecated and will be removed in version 4.0.0; please use #aasm.current_state instead!"
aasm.current_state aasm.current_state
end end
# deprecated # TODO remove this method in v4.0.0
def aasm_enter_initial_state def aasm_enter_initial_state
# warn "#aasm_enter_initial_state is deprecated and will be removed in version 3.2.0; please use #aasm.enter_initial_state instead!" warn "#aasm_enter_initial_state is deprecated and will be removed in version 4.0.0; please use #aasm.enter_initial_state instead!"
aasm.enter_initial_state aasm.enter_initial_state
end end
# deprecated # TODO remove this method in v4.0.0
def aasm_events_for_current_state def aasm_events_for_current_state
# warn "#aasm_events_for_current_state is deprecated and will be removed in version 3.2.0; please use #aasm.events instead!" warn "#aasm_events_for_current_state is deprecated and will be removed in version 4.0.0; please use #aasm.events(aasm.current_state) instead!"
aasm.events(aasm.current_state) aasm.events(aasm.current_state)
end end
# deprecated # TODO remove this method in v4.0.0
def aasm_permissible_events_for_current_state def aasm_permissible_events_for_current_state
# warn "#aasm_permissible_events_for_current_state is deprecated and will be removed in version 3.2.0; please use #aasm.permissible_events instead!" warn "#aasm_permissible_events_for_current_state is deprecated and will be removed in version 4.0.0; please use #aasm.permissible_events instead!"
aasm.permissible_events aasm.permissible_events
end end
# deprecated # TODO remove this method in v4.0.0
def aasm_events_for_state(state_name) def aasm_events_for_state(state_name)
# warn "#aasm_events_for_state(state_name) is deprecated and will be removed in version 3.2.0; please use #aasm.events(state_name) instead!" warn "#aasm_events_for_state(state_name) is deprecated and will be removed in version 4.0.0; please use #aasm.events(state_name) instead!"
aasm.events(state_name) aasm.events(state_name)
end end
# deprecated # TODO remove this method in v4.0.0
def aasm_human_state def aasm_human_state
# warn "#aasm_human_state is deprecated and will be removed in version 3.2.0; please use #aasm.human_state instead!" warn "#aasm_human_state is deprecated and will be removed in version 4.0.0; please use #aasm.human_state instead!"
aasm.human_state aasm.human_state
end end
@ -156,7 +160,7 @@ private
end end
def aasm_fire_event(event_name, options, *args, &block) def aasm_fire_event(event_name, options, *args, &block)
event = self.class.aasm_events[event_name] event = self.class.aasm.events[event_name]
begin begin
old_state = aasm.state_object_for_name(aasm.current_state) old_state = aasm.state_object_for_name(aasm.current_state)
old_state.fire_callbacks(:exit, self) old_state.fire_callbacks(:exit, self)

View file

@ -25,13 +25,16 @@ module AASM
end end
end end
def initial_state def initial_state(new_initial_state=nil)
@state_machine.initial_state if new_initial_state
@state_machine.initial_state = new_initial_state
else
@state_machine.initial_state
end
end end
# define a state # define a state
def state(name, options={}) def state(name, options={})
# @clazz.aasm_state(name, options)
@state_machine.add_state(name, @clazz, options) @state_machine.add_state(name, @clazz, options)
@state_machine.initial_state = name if options[:initial] || !@state_machine.initial_state @state_machine.initial_state = name if options[:initial] || !@state_machine.initial_state
@ -46,8 +49,6 @@ module AASM
# define an event # define an event
def event(name, options={}, &block) def event(name, options={}, &block)
# @clazz.aasm_event(name, options, &block)
@state_machine.events[name] = AASM::Event.new(name, options, &block) @state_machine.events[name] = AASM::Event.new(name, options, &block)
# an addition over standard aasm so that, before firing an event, you can ask # an addition over standard aasm so that, before firing an event, you can ask
@ -78,5 +79,13 @@ module AASM
states.map { |state| state.for_select } states.map { |state| state.for_select }
end end
def from_states_for_state(state, options={})
if options[:transition]
events[options[:transition]].transitions_to_state(state).flatten.map(&:from).flatten
else
events.map {|k,v| v.transitions_to_state(state)}.flatten.map(&:from).flatten
end
end
end end
end end

View file

@ -1,15 +0,0 @@
module AASM
module ClassMethods
def human_event_name(*args)
warn "AASM.human_event_name is deprecated and will be removed in version 3.1.0; please use AASM.aasm_human_event_name instead!"
aasm_human_event_name(*args)
end
end
def human_state
warn "AASM#human_state is deprecated and will be removed in version 3.1.0; please use AASM#aasm_human_state instead!"
aasm_human_state
end
end

View file

@ -36,9 +36,9 @@ module AASM
@transitions.select { |t| t.to == state } @transitions.select { |t| t.to == state }
end end
# deprecated # TODO remove this method in v4.0.0
def all_transitions def all_transitions
# warn "Event#all_transitions is deprecated and will be removed in version 3.2.0; please use Event#transitions instead!" warn "Event#all_transitions is deprecated and will be removed in version 4.0.0; please use Event#transitions instead!"
transitions transitions
end end
@ -56,6 +56,19 @@ module AASM
end end
end end
## DSL interface
def transitions(definitions=nil)
if definitions # define new transitions
# Create a separate transition for each from state to the given state
Array(definitions[:from]).each do |s|
@transitions << AASM::Transition.new(definitions.merge({:from => s.to_sym}))
end
# Create a transition if to is specified without from (transitions from ANY state)
@transitions << AASM::Transition.new(definitions) if @transitions.empty? && definitions[:to]
end
@transitions
end
private private
def update(options = {}, &block) def update(options = {}, &block)
@ -70,7 +83,7 @@ module AASM
def _fire(obj, test, to_state=nil, *args) def _fire(obj, test, to_state=nil, *args)
result = test ? false : nil result = test ? false : nil
if @transitions.map(&:from).any? if @transitions.map(&:from).any?
transitions = transitions_from_state(obj.aasm_current_state) transitions = @transitions.select { |t| t.from == obj.aasm.current_state }
return result if transitions.size == 0 return result if transitions.size == 0
else else
transitions = @transitions transitions = @transitions
@ -118,19 +131,6 @@ module AASM
end end
end end
## DSL interface
def transitions(trans_opts=nil)
if trans_opts # define new transitions
# Create a separate transition for each from state to the given state
Array(trans_opts[:from]).each do |s|
@transitions << AASM::Transition.new(trans_opts.merge({:from => s.to_sym}))
end
# Create a transition if to is specified without from (transitions from ANY state)
@transitions << AASM::Transition.new(trans_opts) if @transitions.empty? && trans_opts[:to]
end
@transitions
end
[:after, :before, :error, :success].each do |callback_name| [:after, :before, :error, :success].each do |callback_name|
define_method callback_name do |*args, &block| define_method callback_name do |*args, &block|
options[callback_name] = Array(options[callback_name]) options[callback_name] = Array(options[callback_name])

View file

@ -15,7 +15,7 @@ module AASM
end end
def enter_initial_state def enter_initial_state
state_name = determine_state_name(@instance.class.aasm_initial_state) state_name = determine_state_name(@instance.class.aasm.initial_state)
state_object = state_object_for_name(state_name) state_object = state_object_for_name(state_name)
state_object.fire_callbacks(:before_enter, @instance) state_object.fire_callbacks(:before_enter, @instance)

View file

@ -71,10 +71,10 @@ module AASM
# Writes <tt>state</tt> to the state column and persists it to the database # Writes <tt>state</tt> to the state column and persists it to the database
# #
# foo = Foo.find(1) # foo = Foo.find(1)
# foo.aasm_current_state # => :opened # foo.aasm.current_state # => :opened
# foo.close! # foo.close!
# foo.aasm_current_state # => :closed # foo.aasm.current_state # => :closed
# Foo.find(1).aasm_current_state # => :closed # Foo.find(1).aasm.current_state # => :closed
# #
# NOTE: intended to be called from an event # NOTE: intended to be called from an event
def aasm_write_state(state) def aasm_write_state(state)
@ -97,13 +97,13 @@ module AASM
# Writes <tt>state</tt> to the state column, but does not persist it to the database # Writes <tt>state</tt> to the state column, but does not persist it to the database
# #
# foo = Foo.find(1) # foo = Foo.find(1)
# foo.aasm_current_state # => :opened # foo.aasm.current_state # => :opened
# foo.close # foo.close
# foo.aasm_current_state # => :closed # foo.aasm.current_state # => :closed
# Foo.find(1).aasm_current_state # => :opened # Foo.find(1).aasm.current_state # => :opened
# foo.save # foo.save
# foo.aasm_current_state # => :closed # foo.aasm.current_state # => :closed
# Foo.find(1).aasm_current_state # => :closed # Foo.find(1).aasm.current_state # => :closed
# #
# NOTE: intended to be called from an event # NOTE: intended to be called from an event
def aasm_write_state_without_persistence(state) def aasm_write_state_without_persistence(state)

View file

@ -35,7 +35,7 @@ module AASM
def aasm_read_state def aasm_read_state
state = send(self.class.aasm_column) state = send(self.class.aasm_column)
if new_record? if new_record?
state.blank? ? aasm.determine_state_name(self.class.aasm_initial_state) : state.to_sym state.blank? ? aasm.determine_state_name(self.class.aasm.initial_state) : state.to_sym
else else
state.nil? ? nil : state.to_sym state.nil? ? nil : state.to_sym
end end

View file

@ -66,10 +66,10 @@ module AASM
# using update_attribute (which bypasses validation) # using update_attribute (which bypasses validation)
# #
# foo = Foo.find(1) # foo = Foo.find(1)
# foo.aasm_current_state # => :opened # foo.aasm.current_state # => :opened
# foo.close! # foo.close!
# foo.aasm_current_state # => :closed # foo.aasm.current_state # => :closed
# Foo.find(1).aasm_current_state # => :closed # Foo.find(1).aasm.current_state # => :closed
# #
# NOTE: intended to be called from an event # NOTE: intended to be called from an event
def aasm_write_state(state) def aasm_write_state(state)
@ -87,13 +87,13 @@ module AASM
# Writes <tt>state</tt> to the state column, but does not persist it to the database # Writes <tt>state</tt> to the state column, but does not persist it to the database
# #
# foo = Foo.find(1) # foo = Foo.find(1)
# foo.aasm_current_state # => :opened # foo.aasm.current_state # => :opened
# foo.close # foo.close
# foo.aasm_current_state # => :closed # foo.aasm.current_state # => :closed
# Foo.find(1).aasm_current_state # => :opened # Foo.find(1).aasm.current_state # => :opened
# foo.save # foo.save
# foo.aasm_current_state # => :closed # foo.aasm.current_state # => :closed
# Foo.find(1).aasm_current_state # => :closed # Foo.find(1).aasm.current_state # => :closed
# #
# NOTE: intended to be called from an event # NOTE: intended to be called from an event
def aasm_write_state_without_persistence(state) def aasm_write_state_without_persistence(state)

View file

@ -1,41 +0,0 @@
class CallbackOldDsl
include AASM
aasm_initial_state :open
aasm_state :open,
:before_enter => :before_enter_open,
:after_enter => :after_enter_open,
:before_exit => :before_exit_open,
:exit => :exit_open,
:after_exit => :after_exit_open
aasm_state :closed,
:before_enter => :before_enter_closed,
:enter => :enter_closed,
:after_enter => :after_enter_closed,
:before_exit => :before_exit_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
def enter_closed; end
def exit_open; end
end

View file

@ -2,7 +2,7 @@ class NoScopeMongoid
include Mongoid::Document include Mongoid::Document
include AASM include AASM
field :status, type: String field :status, :type => String
aasm :create_scopes => false, :column => :status do aasm :create_scopes => false, :column => :status do
state :ignored_scope state :ignored_scope

View file

@ -2,9 +2,10 @@ class SimpleMongoid
include Mongoid::Document include Mongoid::Document
include AASM include AASM
field :status, type: String field :status, :type => String
aasm_column :status aasm column: :status do
aasm_state :unknown_scope state :unknown_scope
aasm_state :new state :new
end
end end

View file

@ -2,7 +2,7 @@ class SimpleNewDslMongoid
include Mongoid::Document include Mongoid::Document
include AASM include AASM
field :status, type: String field :status, :type => String
aasm :column => :status aasm :column => :status
aasm do aasm do

View file

@ -2,16 +2,18 @@ module Models
class Process class Process
include AASM include AASM
aasm_state :sleeping aasm do
aasm_state :running state :sleeping
aasm_state :suspended state :running
state :suspended
aasm_event :start do event :start do
transitions :from => :sleeping, :to => :running transitions :from => :sleeping, :to => :running
end end
aasm_event :stop do event :stop do
transitions :from => :running, :to => :suspended transitions :from => :running, :to => :suspended
end
end end
end end

View file

@ -36,13 +36,6 @@ class Transient < ActiveRecord::Base
include AASM include AASM
end end
class Simple < ActiveRecord::Base
include AASM
aasm_column :status
aasm_state :unknown_scope
aasm_state :new
end
class SimpleNewDsl < ActiveRecord::Base class SimpleNewDsl < ActiveRecord::Base
include AASM include AASM
aasm :column => :status aasm :column => :status
@ -59,9 +52,6 @@ class NoScope < ActiveRecord::Base
end end
end end
class Derivate < Simple
end
class DerivateNewDsl < SimpleNewDsl class DerivateNewDsl < SimpleNewDsl
end end
@ -72,8 +62,10 @@ class Thief < ActiveRecord::Base
set_table_name "thieves" set_table_name "thieves"
end end
include AASM include AASM
aasm_initial_state Proc.new { |thief| thief.skilled ? :rich : :jailed } aasm do
aasm_state :rich state :rich
aasm_state :jailed state :jailed
initial_state Proc.new {|thief| thief.skilled ? :rich : :jailed }
end
attr_accessor :skilled, :aasm_state attr_accessor :skilled, :aasm_state
end end

View file

@ -1,23 +1,5 @@
require 'spec_helper' require 'spec_helper'
describe 'callbacks for the old DSL' do
let(:callback) {CallbackOldDsl.new}
it "should get close callbacks" do
callback.should_receive(:exit_open).once.ordered
callback.should_receive(:before).once.ordered
callback.should_receive(:before_exit_open).once.ordered # these should be before the state changes
callback.should_receive(:before_enter_closed).once.ordered
callback.should_receive(:enter_closed).once.ordered
callback.should_receive(:aasm_write_state).once.ordered.and_return(true) # this is when the state changes
callback.should_receive(:after_exit_open).once.ordered # these should be after the state changes
callback.should_receive(:after_enter_closed).once.ordered
callback.should_receive(:after).once.ordered
callback.close!
end
end
describe 'callbacks for the new DSL' do describe 'callbacks for the new DSL' do
let(:callback) {CallbackNewDsl.new} let(:callback) {CallbackNewDsl.new}
@ -72,8 +54,10 @@ describe 'event callbacks' do
describe "with an error callback defined" do describe "with an error callback defined" do
before do before do
class Foo class Foo
aasm_event :safe_close, :success => :success_callback, :error => :error_callback do aasm do
transitions :to => :closed, :from => [:open] event :safe_close, :success => :success_callback, :error => :error_callback do
transitions :to => :closed, :from => [:open]
end
end end
end end

View file

@ -4,7 +4,7 @@ describe 'on initialization' do
let(:auth) {AuthMachine.new} let(:auth) {AuthMachine.new}
it 'should be in the pending state' do it 'should be in the pending state' do
auth.aasm_current_state.should == :pending auth.aasm.current_state.should == :pending
end end
it 'should have an activation code' do it 'should have an activation code' do
@ -55,14 +55,14 @@ describe 'when being unsuspended' do
auth.suspend! auth.suspend!
auth.unsuspend! auth.unsuspend!
auth.aasm_current_state.should == :active auth.aasm.current_state.should == :active
end end
it 'should be pending if not previously activated, but an activation code is present' do it 'should be pending if not previously activated, but an activation code is present' do
auth.suspend! auth.suspend!
auth.unsuspend! auth.unsuspend!
auth.aasm_current_state.should == :pending auth.aasm.current_state.should == :pending
end end
it 'should be passive if not previously activated and there is no activation code' do it 'should be passive if not previously activated and there is no activation code' do
@ -70,6 +70,6 @@ describe 'when being unsuspended' do
auth.suspend! auth.suspend!
auth.unsuspend! auth.unsuspend!
auth.aasm_current_state.should == :passive auth.aasm.current_state.should == :passive
end end
end end

View file

@ -26,7 +26,7 @@ describe 'adding an event' do
end end
it 'should create transitions' do it 'should create transitions' do
transitions = event.all_transitions transitions = event.transitions
transitions[0].from.should == :open transitions[0].from.should == :open
transitions[0].to.should == :closed transitions[0].to.should == :closed
transitions[1].from.should == :received transitions[1].from.should == :received
@ -60,8 +60,7 @@ end
describe 'firing an event' do describe 'firing an event' do
it 'should return nil if the transitions are empty' do it 'should return nil if the transitions are empty' do
obj = double('object') obj = double('object', :aasm => double('aasm', :current_state => 'open'))
obj.stub(:aasm_current_state)
event = AASM::Event.new(:event) event = AASM::Event.new(:event)
event.fire(obj).should be_nil event.fire(obj).should be_nil
@ -72,8 +71,7 @@ describe 'firing an event' do
transitions :to => :closed, :from => [:open, :received] transitions :to => :closed, :from => [:open, :received]
end end
obj = double('object') obj = double('object', :aasm => double('aasm', :current_state => :open))
obj.stub(:aasm_current_state).and_return(:open)
event.fire(obj).should == :closed event.fire(obj).should == :closed
end end
@ -83,8 +81,7 @@ describe 'firing an event' do
transitions :to => :closed, :from => [:open, :received], :guard => :guard_fn transitions :to => :closed, :from => [:open, :received], :guard => :guard_fn
end end
obj = double('object') obj = double('object', :aasm => double('aasm', :current_state => :open))
obj.stub(:aasm_current_state).and_return(:open)
obj.should_receive(:guard_fn).with('arg1', 'arg2').and_return(true) obj.should_receive(:guard_fn).with('arg1', 'arg2').and_return(true)
event.fire(obj, nil, 'arg1', 'arg2').should == :closed event.fire(obj, nil, 'arg1', 'arg2').should == :closed
@ -96,8 +93,10 @@ describe 'should fire callbacks' do
describe 'success' do describe 'success' do
it "if it's a symbol" do it "if it's a symbol" do
ThisNameBetterNotBeInUse.instance_eval { ThisNameBetterNotBeInUse.instance_eval {
aasm_event :with_symbol, :success => :symbol_success_callback do aasm do
transitions :to => :symbol, :from => [:initial] event :with_symbol, :success => :symbol_success_callback do
transitions :to => :symbol, :from => [:initial]
end
end end
} }
@ -108,8 +107,10 @@ describe 'should fire callbacks' do
it "if it's a string" do it "if it's a string" do
ThisNameBetterNotBeInUse.instance_eval { ThisNameBetterNotBeInUse.instance_eval {
aasm_event :with_string, :success => 'string_success_callback' do aasm do
transitions :to => :string, :from => [:initial] event :with_string, :success => 'string_success_callback' do
transitions :to => :string, :from => [:initial]
end
end end
} }
@ -120,8 +121,10 @@ describe 'should fire callbacks' do
it "if passed an array of strings and/or symbols" do it "if passed an array of strings and/or symbols" do
ThisNameBetterNotBeInUse.instance_eval { ThisNameBetterNotBeInUse.instance_eval {
aasm_event :with_array, :success => [:success_callback1, 'success_callback2'] do aasm do
transitions :to => :array, :from => [:initial] event :with_array, :success => [:success_callback1, 'success_callback2'] do
transitions :to => :array, :from => [:initial]
end
end end
} }
@ -133,8 +136,10 @@ describe 'should fire callbacks' do
it "if passed an array of strings and/or symbols and/or procs" do it "if passed an array of strings and/or symbols and/or procs" do
ThisNameBetterNotBeInUse.instance_eval { ThisNameBetterNotBeInUse.instance_eval {
aasm_event :with_array_including_procs, :success => [:success_callback1, 'success_callback2', lambda { proc_success_callback }] do aasm do
transitions :to => :array, :from => [:initial] event :with_array_including_procs, :success => [:success_callback1, 'success_callback2', lambda { proc_success_callback }] do
transitions :to => :array, :from => [:initial]
end
end end
} }
@ -147,8 +152,10 @@ describe 'should fire callbacks' do
it "if it's a proc" do it "if it's a proc" do
ThisNameBetterNotBeInUse.instance_eval { ThisNameBetterNotBeInUse.instance_eval {
aasm_event :with_proc, :success => lambda { proc_success_callback } do aasm do
transitions :to => :proc, :from => [:initial] event :with_proc, :success => lambda { proc_success_callback } do
transitions :to => :proc, :from => [:initial]
end
end end
} }
@ -161,14 +168,16 @@ describe 'should fire callbacks' do
describe 'after' do describe 'after' do
it "if they set different ways" do it "if they set different ways" do
ThisNameBetterNotBeInUse.instance_eval do ThisNameBetterNotBeInUse.instance_eval do
aasm_event :with_afters, :after => :do_one_thing_after do aasm do
after do event :with_afters, :after => :do_one_thing_after do
do_another_thing_after_too after do
do_another_thing_after_too
end
after do
do_third_thing_at_last
end
transitions :to => :proc, :from => [:initial]
end end
after do
do_third_thing_at_last
end
transitions :to => :proc, :from => [:initial]
end end
end end
@ -183,11 +192,13 @@ describe 'should fire callbacks' do
describe 'before' do describe 'before' do
it "if it's a proc" do it "if it's a proc" do
ThisNameBetterNotBeInUse.instance_eval do ThisNameBetterNotBeInUse.instance_eval do
aasm_event :before_as_proc do aasm do
before do event :before_as_proc do
do_something_before before do
do_something_before
end
transitions :to => :proc, :from => [:initial]
end end
transitions :to => :proc, :from => [:initial]
end end
end end
@ -199,11 +210,13 @@ describe 'should fire callbacks' do
it 'in right order' do it 'in right order' do
ThisNameBetterNotBeInUse.instance_eval do ThisNameBetterNotBeInUse.instance_eval do
aasm_event :in_right_order, :after => :do_something_after do aasm do
before do event :in_right_order, :after => :do_something_after do
do_something_before before do
do_something_before
end
transitions :to => :proc, :from => [:initial]
end end
transitions :to => :proc, :from => [:initial]
end end
end end
@ -219,22 +232,22 @@ describe 'parametrised events' do
it 'should transition to specified next state (sleeping to showering)' do it 'should transition to specified next state (sleeping to showering)' do
pe.wakeup!(:showering) pe.wakeup!(:showering)
pe.aasm_current_state.should == :showering pe.aasm.current_state.should == :showering
end end
it 'should transition to specified next state (sleeping to working)' do it 'should transition to specified next state (sleeping to working)' do
pe.wakeup!(:working) pe.wakeup!(:working)
pe.aasm_current_state.should == :working pe.aasm.current_state.should == :working
end end
it 'should transition to default (first or showering) state' do it 'should transition to default (first or showering) state' do
pe.wakeup! pe.wakeup!
pe.aasm_current_state.should == :showering pe.aasm.current_state.should == :showering
end end
it 'should transition to default state when on_transition invoked' do it 'should transition to default state when on_transition invoked' do
pe.dress!(nil, 'purple', 'dressy') pe.dress!(nil, 'purple', 'dressy')
pe.aasm_current_state.should == :working pe.aasm.current_state.should == :working
end end
it 'should call on_transition method with args' do it 'should call on_transition method with args' do

View file

@ -5,8 +5,8 @@ class Banker
aasm do aasm do
state :retired state :retired
state :selling_bad_mortgages state :selling_bad_mortgages
initial_state Proc.new { |banker| banker.rich? ? :retired : :selling_bad_mortgages }
end end
aasm_initial_state Proc.new { |banker| banker.rich? ? :retired : :selling_bad_mortgages }
RICH = 1_000_000 RICH = 1_000_000
attr_accessor :balance attr_accessor :balance
def initialize(balance = 0); self.balance = balance; end def initialize(balance = 0); self.balance = balance; end
@ -17,12 +17,11 @@ describe 'initial states' do
let(:bar) {Bar.new} let(:bar) {Bar.new}
it 'should use the first state defined if no initial state is given' do it 'should use the first state defined if no initial state is given' do
bar.aasm_current_state.should == :read bar.aasm.current_state.should == :read
# bar.aasm.current_state.should == :read # not yet supported
end end
it 'should determine initial state from the Proc results' do it 'should determine initial state from the Proc results' do
Banker.new(Banker::RICH - 1).aasm_current_state.should == :selling_bad_mortgages Banker.new(Banker::RICH - 1).aasm.current_state.should == :selling_bad_mortgages
Banker.new(Banker::RICH + 1).aasm_current_state.should == :retired Banker.new(Banker::RICH + 1).aasm.current_state.should == :retired
end end
end end

View file

@ -1,19 +1,6 @@
require 'spec_helper' require 'spec_helper'
describe 'inspection for common cases' do describe 'inspection for common cases' do
it 'should support the old DSL' do
Foo.should respond_to(:aasm_states)
Foo.aasm_states.should include(:open)
Foo.aasm_states.should include(:closed)
Foo.should respond_to(:aasm_initial_state)
Foo.aasm_initial_state.should == :open
Foo.should respond_to(:aasm_events)
Foo.aasm_events.should include(:close)
Foo.aasm_events.should include(:null)
end
it 'should support the new DSL' do it 'should support the new DSL' do
Foo.aasm.should respond_to(:states) Foo.aasm.should respond_to(:states)
Foo.aasm.states.should include(:open) Foo.aasm.states.should include(:open)
@ -74,35 +61,35 @@ end
describe "special cases" do describe "special cases" do
it "should support valid a state name" do it "should support valid a state name" do
Argument.aasm_states.should include(:invalid) Argument.aasm.states.should include(:invalid)
Argument.aasm_states.should include(:valid) Argument.aasm.states.should include(:valid)
argument = Argument.new argument = Argument.new
argument.invalid?.should be_true argument.invalid?.should be_true
argument.aasm_current_state.should == :invalid argument.aasm.current_state.should == :invalid
argument.valid! argument.valid!
argument.valid?.should be_true argument.valid?.should be_true
argument.aasm_current_state.should == :valid argument.aasm.current_state.should == :valid
end end
end end
describe :aasm_states_for_select do describe 'aasm.states_for_select' do
it "should return a select friendly array of states" do it "should return a select friendly array of states" do
Foo.should respond_to(:aasm_states_for_select) Foo.aasm.should respond_to(:states_for_select)
Foo.aasm_states_for_select.should == [['Open', 'open'], ['Closed', 'closed']] Foo.aasm.states_for_select.should == [['Open', 'open'], ['Closed', 'closed']]
end end
end end
describe :aasm_from_states_for_state do describe 'aasm.from_states_for_state' do
it "should return all from states for a state" do it "should return all from states for a state" do
AuthMachine.should respond_to(:aasm_from_states_for_state) AuthMachine.aasm.should respond_to(:from_states_for_state)
froms = AuthMachine.aasm_from_states_for_state(:active) froms = AuthMachine.aasm.from_states_for_state(:active)
[:pending, :passive, :suspended].each {|from| froms.should include(from)} [:pending, :passive, :suspended].each {|from| froms.should include(from)}
end end
it "should return from states for a state for a particular transition only" do it "should return from states for a state for a particular transition only" do
froms = AuthMachine.aasm_from_states_for_state(:active, :transition => :unsuspend) froms = AuthMachine.aasm.from_states_for_state(:active, :transition => :unsuspend)
[:suspended].each {|from| froms.should include(from)} [:suspended].each {|from| froms.should include(from)}
end end
end end

View file

@ -10,12 +10,12 @@ class LocalizerTestModel < ActiveRecord::Base
attr_accessor :aasm_state attr_accessor :aasm_state
aasm_initial_state :opened aasm do
aasm_state :opened state :opened, :initial => true
aasm_state :closed state :closed
event :close
aasm_event :close event :open
aasm_event :open end
end end
describe 'localized state names' do describe 'localized state names' do
@ -52,13 +52,13 @@ describe AASM::Localizer, "new style" do
let (:foo_opened) { LocalizerTestModel.new } let (:foo_opened) { LocalizerTestModel.new }
let (:foo_closed) { LocalizerTestModel.new.tap { |x| x.aasm_state = :closed } } let (:foo_closed) { LocalizerTestModel.new.tap { |x| x.aasm_state = :closed } }
context 'aasm_human_state' do context 'aasm.human_state' do
it 'should return translated state value' do it 'should return translated state value' do
foo_opened.aasm_human_state.should == "It's open now!" foo_opened.aasm.human_state.should == "It's open now!"
end end
it 'should return humanized value if not localized' do it 'should return humanized value if not localized' do
foo_closed.aasm_human_state.should == "Closed" foo_closed.aasm.human_state.should == "Closed"
end end
end end
@ -87,13 +87,13 @@ describe AASM::Localizer, "deprecated style" do
let (:foo_opened) { LocalizerTestModel.new } let (:foo_opened) { LocalizerTestModel.new }
let (:foo_closed) { LocalizerTestModel.new.tap { |x| x.aasm_state = :closed } } let (:foo_closed) { LocalizerTestModel.new.tap { |x| x.aasm_state = :closed } }
context 'aasm_human_state' do context 'aasm.human_state' do
it 'should return translated state value' do it 'should return translated state value' do
foo_opened.aasm_human_state.should == "It's open now!" foo_opened.aasm.human_state.should == "It's open now!"
end end
it 'should return humanized value if not localized' do it 'should return humanized value if not localized' do
foo_closed.aasm_human_state.should == "Closed" foo_closed.aasm.human_state.should == "Closed"
end end
end end

View file

@ -24,24 +24,24 @@ describe "instance methods" do
end end
it "should return the initial state when new and the aasm field is nil" do it "should return the initial state when new and the aasm field is nil" do
gate.aasm_current_state.should == :opened gate.aasm.current_state.should == :opened
end end
it "should return the aasm column when new and the aasm field is not nil" do it "should return the aasm column when new and the aasm field is not nil" do
gate.aasm_state = "closed" gate.aasm_state = "closed"
gate.aasm_current_state.should == :closed gate.aasm.current_state.should == :closed
end end
it "should return the aasm column when not new and the aasm_column is not nil" do it "should return the aasm column when not new and the aasm_column is not nil" do
gate.stub(:new_record?).and_return(false) gate.stub(:new_record?).and_return(false)
gate.aasm_state = "state" gate.aasm_state = "state"
gate.aasm_current_state.should == :state gate.aasm.current_state.should == :state
end end
it "should allow a nil state" do it "should allow a nil state" do
gate.stub(:new_record?).and_return(false) gate.stub(:new_record?).and_return(false)
gate.aasm_state = nil gate.aasm_state = nil
gate.aasm_current_state.should be_nil gate.aasm.current_state.should be_nil
end end
it "should call aasm_ensure_initial_state on validation before create" do it "should call aasm_ensure_initial_state on validation before create" do
@ -59,15 +59,11 @@ end
describe 'subclasses' do describe 'subclasses' do
it "should have the same states as its parent class" do it "should have the same states as its parent class" do
Derivate.aasm_states.should == Simple.aasm_states DerivateNewDsl.aasm.states.should == SimpleNewDsl.aasm.states
end end
it "should have the same events as its parent class" do it "should have the same events as its parent class" do
Derivate.aasm_events.should == Simple.aasm_events DerivateNewDsl.aasm.events.should == SimpleNewDsl.aasm.events
end
it "should have the same column as its parent class" do
Derivate.aasm_column.should == :status
end end
it "should have the same column as its parent even for the new dsl" do it "should have the same column as its parent even for the new dsl" do
@ -76,26 +72,7 @@ describe 'subclasses' do
end end
end end
describe "named scopes with the old DSL" do
context "Does not already respond_to? the scope name" do
it "should add a scope" do
Simple.should respond_to(:unknown_scope)
SimpleNewDsl.unknown_scope.is_a?(ActiveRecord::Relation).should be_true
end
end
context "Already respond_to? the scope name" do
it "should not add a scope" do
Simple.should respond_to(:new)
Simple.new.class.should == Simple
end
end
end
describe "named scopes with the new DSL" do describe "named scopes with the new DSL" do
context "Does not already respond_to? the scope name" do context "Does not already respond_to? the scope name" do
it "should add a scope" do it "should add a scope" do
SimpleNewDsl.should respond_to(:unknown_scope) SimpleNewDsl.should respond_to(:unknown_scope)
@ -119,8 +96,8 @@ end
describe 'initial states' do describe 'initial states' do
it 'should support conditions' do it 'should support conditions' do
Thief.new(:skilled => true).aasm_current_state.should == :rich Thief.new(:skilled => true).aasm.current_state.should == :rich
Thief.new(:skilled => false).aasm_current_state.should == :jailed Thief.new(:skilled => false).aasm.current_state.should == :jailed
end end
end end

View file

@ -20,8 +20,7 @@ describe 'state machine' do
let(:payment) {Payment.new} let(:payment) {Payment.new}
it 'starts with an initial state' do it 'starts with an initial state' do
payment.aasm_current_state.should == :initialised payment.aasm.current_state.should == :initialised
# payment.aasm.current_state.should == :initialised # not yet supported
payment.should respond_to(:initialised?) payment.should respond_to(:initialised?)
payment.should be_initialised payment.should be_initialised
end end

View file

@ -4,18 +4,18 @@ describe 'subclassing' do
let(:son) {Son.new} let(:son) {Son.new}
it 'should have the parent states' do it 'should have the parent states' do
Foo.aasm_states.each do |state| Foo.aasm.states.each do |state|
FooTwo.aasm_states.should include(state) FooTwo.aasm.states.should include(state)
end end
Baz.aasm_states.should == Bar.aasm_states Baz.aasm.states.should == Bar.aasm.states
end end
it 'should not add the child states to the parent machine' do it 'should not add the child states to the parent machine' do
Foo.aasm_states.should_not include(:foo) Foo.aasm.states.should_not include(:foo)
end end
it "should have the same events as its parent" do it "should have the same events as its parent" do
Baz.aasm_events.should == Bar.aasm_events Baz.aasm.events.should == Bar.aasm.events
end end
it 'should know how to respond to `may_add_details?`' do it 'should know how to respond to `may_add_details?`' do
@ -24,8 +24,8 @@ describe 'subclassing' do
it 'should not break if I call Son#update_state' do it 'should not break if I call Son#update_state' do
son.update_state son.update_state
son.aasm_current_state.should == :pending_details_confirmation son.aasm.current_state.should == :pending_details_confirmation
end end
end end