mirror of
https://github.com/aasm/aasm
synced 2023-03-27 23:22:41 -04:00
no need for WriteState mixin anymore (to keep adding persistence simple)
This commit is contained in:
parent
52181d8017
commit
95ef7fc834
8 changed files with 151 additions and 102 deletions
10
API
10
API
|
@ -7,3 +7,13 @@ Overwrite method to read the current state
|
||||||
# retrieve the current state manually
|
# retrieve the current state manually
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Overwrite method to write the current state
|
||||||
|
|
||||||
|
class MyClass
|
||||||
|
include AASM
|
||||||
|
|
||||||
|
def aasm_write_state
|
||||||
|
# store the current state manually
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
@ -86,6 +86,11 @@ module AASM
|
||||||
aasm.enter_initial_state
|
aasm.enter_initial_state
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# may be overwritten by persistence mixins
|
||||||
|
def aasm_write_state(new_state)
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
# deprecated
|
# deprecated
|
||||||
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 3.2.0; please use #aasm.state instead!"
|
||||||
|
|
|
@ -69,10 +69,7 @@ module AASM
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_current_state_with_persistence(state)
|
def set_current_state_with_persistence(state)
|
||||||
save_success = true
|
|
||||||
if @instance.respond_to?(:aasm_write_state) || @instance.private_methods.include?('aasm_write_state')
|
|
||||||
save_success = @instance.aasm_write_state(state)
|
save_success = @instance.aasm_write_state(state)
|
||||||
end
|
|
||||||
self.current_state = state if save_success
|
self.current_state = state if save_success
|
||||||
save_success
|
save_success
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,7 +7,6 @@ module AASM
|
||||||
# * includes InstanceMethods
|
# * includes InstanceMethods
|
||||||
#
|
#
|
||||||
# Unless the corresponding methods are already defined, it includes
|
# Unless the corresponding methods are already defined, it includes
|
||||||
# * WriteState
|
|
||||||
# * WriteStateWithoutPersistence
|
# * WriteStateWithoutPersistence
|
||||||
#
|
#
|
||||||
# Adds
|
# Adds
|
||||||
|
@ -34,7 +33,6 @@ module AASM
|
||||||
base.send(:include, AASM::Persistence::Base)
|
base.send(:include, AASM::Persistence::Base)
|
||||||
base.extend AASM::Persistence::ActiveRecordPersistence::ClassMethods
|
base.extend AASM::Persistence::ActiveRecordPersistence::ClassMethods
|
||||||
base.send(:include, AASM::Persistence::ActiveRecordPersistence::InstanceMethods)
|
base.send(:include, AASM::Persistence::ActiveRecordPersistence::InstanceMethods)
|
||||||
base.send(:include, AASM::Persistence::ActiveRecordPersistence::WriteState) unless base.method_defined?(:aasm_write_state)
|
|
||||||
base.send(:include, AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence) unless base.method_defined?(:aasm_write_state_without_persistence)
|
base.send(:include, AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence) unless base.method_defined?(:aasm_write_state_without_persistence)
|
||||||
|
|
||||||
if ActiveRecord::VERSION::MAJOR >= 3
|
if ActiveRecord::VERSION::MAJOR >= 3
|
||||||
|
@ -74,6 +72,32 @@ module AASM
|
||||||
|
|
||||||
module InstanceMethods
|
module InstanceMethods
|
||||||
|
|
||||||
|
# Writes <tt>state</tt> to the state column and persists it to the database
|
||||||
|
#
|
||||||
|
# foo = Foo.find(1)
|
||||||
|
# foo.aasm_current_state # => :opened
|
||||||
|
# foo.close!
|
||||||
|
# foo.aasm_current_state # => :closed
|
||||||
|
# Foo.find(1).aasm_current_state # => :closed
|
||||||
|
#
|
||||||
|
# NOTE: intended to be called from an event
|
||||||
|
def aasm_write_state(state)
|
||||||
|
old_value = read_attribute(self.class.aasm_column)
|
||||||
|
write_attribute(self.class.aasm_column, state.to_s)
|
||||||
|
|
||||||
|
success = if AASM::StateMachine[self.class].config.skip_validation_on_save
|
||||||
|
self.class.update_all({ self.class.aasm_column => state.to_s }, self.class.primary_key => self.id) == 1
|
||||||
|
else
|
||||||
|
self.save
|
||||||
|
end
|
||||||
|
unless success
|
||||||
|
write_attribute(self.class.aasm_column, old_value)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# Ensures that if the aasm_state column is nil and the record is new
|
# Ensures that if the aasm_state column is nil and the record is new
|
||||||
|
@ -100,8 +124,7 @@ module AASM
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end # InstanceMethods
|
||||||
end
|
|
||||||
|
|
||||||
module WriteStateWithoutPersistence
|
module WriteStateWithoutPersistence
|
||||||
# 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
|
||||||
|
@ -121,34 +144,6 @@ module AASM
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
module WriteState
|
|
||||||
# Writes <tt>state</tt> to the state column and persists it to the database
|
|
||||||
#
|
|
||||||
# foo = Foo.find(1)
|
|
||||||
# foo.aasm_current_state # => :opened
|
|
||||||
# foo.close!
|
|
||||||
# foo.aasm_current_state # => :closed
|
|
||||||
# Foo.find(1).aasm_current_state # => :closed
|
|
||||||
#
|
|
||||||
# NOTE: intended to be called from an event
|
|
||||||
def aasm_write_state(state)
|
|
||||||
old_value = read_attribute(self.class.aasm_column)
|
|
||||||
write_attribute(self.class.aasm_column, state.to_s)
|
|
||||||
|
|
||||||
success = if AASM::StateMachine[self.class].config.skip_validation_on_save
|
|
||||||
self.class.update_all({ self.class.aasm_column => state.to_s }, self.class.primary_key => self.id) == 1
|
|
||||||
else
|
|
||||||
self.save
|
|
||||||
end
|
|
||||||
unless success
|
|
||||||
write_attribute(self.class.aasm_column, old_value)
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,7 +7,6 @@ module AASM
|
||||||
# * includes InstanceMethods
|
# * includes InstanceMethods
|
||||||
#
|
#
|
||||||
# Unless the corresponding methods are already defined, it includes
|
# Unless the corresponding methods are already defined, it includes
|
||||||
# * WriteState
|
|
||||||
# * WriteStateWithoutPersistence
|
# * WriteStateWithoutPersistence
|
||||||
#
|
#
|
||||||
# Adds
|
# Adds
|
||||||
|
@ -36,7 +35,6 @@ module AASM
|
||||||
base.send(:include, AASM::Persistence::Base)
|
base.send(:include, AASM::Persistence::Base)
|
||||||
base.extend AASM::Persistence::MongoidPersistence::ClassMethods
|
base.extend AASM::Persistence::MongoidPersistence::ClassMethods
|
||||||
base.send(:include, AASM::Persistence::MongoidPersistence::InstanceMethods)
|
base.send(:include, AASM::Persistence::MongoidPersistence::InstanceMethods)
|
||||||
base.send(:include, AASM::Persistence::MongoidPersistence::WriteState) unless base.method_defined?(:aasm_write_state)
|
|
||||||
base.send(:include, AASM::Persistence::MongoidPersistence::WriteStateWithoutPersistence) unless base.method_defined?(:aasm_write_state_without_persistence)
|
base.send(:include, AASM::Persistence::MongoidPersistence::WriteStateWithoutPersistence) unless base.method_defined?(:aasm_write_state_without_persistence)
|
||||||
|
|
||||||
# Mongoid's Validatable gem dependency goes not have a before_validation_on_xxx hook yet.
|
# Mongoid's Validatable gem dependency goes not have a before_validation_on_xxx hook yet.
|
||||||
|
@ -68,48 +66,6 @@ module AASM
|
||||||
|
|
||||||
module InstanceMethods
|
module InstanceMethods
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
# Ensures that if the aasm_state column is nil and the record is new
|
|
||||||
# that the initial state gets populated before validation on create
|
|
||||||
#
|
|
||||||
# foo = Foo.new
|
|
||||||
# foo.aasm_state # => nil
|
|
||||||
# foo.valid?
|
|
||||||
# foo.aasm_state # => "open" (where :open is the initial state)
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# foo = Foo.find(:first)
|
|
||||||
# foo.aasm_state # => 1
|
|
||||||
# foo.aasm_state = nil
|
|
||||||
# foo.valid?
|
|
||||||
# foo.aasm_state # => nil
|
|
||||||
#
|
|
||||||
def aasm_ensure_initial_state
|
|
||||||
send("#{self.class.aasm_column}=", aasm.enter_initial_state.to_s) if send(self.class.aasm_column).blank?
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
module WriteStateWithoutPersistence
|
|
||||||
# Writes <tt>state</tt> to the state column, but does not persist it to the database
|
|
||||||
#
|
|
||||||
# foo = Foo.find(1)
|
|
||||||
# foo.aasm_current_state # => :opened
|
|
||||||
# foo.close
|
|
||||||
# foo.aasm_current_state # => :closed
|
|
||||||
# Foo.find(1).aasm_current_state # => :opened
|
|
||||||
# foo.save
|
|
||||||
# foo.aasm_current_state # => :closed
|
|
||||||
# Foo.find(1).aasm_current_state # => :closed
|
|
||||||
#
|
|
||||||
# NOTE: intended to be called from an event
|
|
||||||
def aasm_write_state_without_persistence(state)
|
|
||||||
write_attribute(self.class.aasm_column, state.to_s)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
module WriteState
|
|
||||||
# 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
|
||||||
# using update_attribute (which bypasses validation)
|
# using update_attribute (which bypasses validation)
|
||||||
#
|
#
|
||||||
|
@ -131,6 +87,45 @@ module AASM
|
||||||
|
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# Ensures that if the aasm_state column is nil and the record is new
|
||||||
|
# that the initial state gets populated before validation on create
|
||||||
|
#
|
||||||
|
# foo = Foo.new
|
||||||
|
# foo.aasm_state # => nil
|
||||||
|
# foo.valid?
|
||||||
|
# foo.aasm_state # => "open" (where :open is the initial state)
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# foo = Foo.find(:first)
|
||||||
|
# foo.aasm_state # => 1
|
||||||
|
# foo.aasm_state = nil
|
||||||
|
# foo.valid?
|
||||||
|
# foo.aasm_state # => nil
|
||||||
|
#
|
||||||
|
def aasm_ensure_initial_state
|
||||||
|
send("#{self.class.aasm_column}=", aasm.enter_initial_state.to_s) if send(self.class.aasm_column).blank?
|
||||||
|
end
|
||||||
|
end # InstanceMethods
|
||||||
|
|
||||||
|
module WriteStateWithoutPersistence
|
||||||
|
# Writes <tt>state</tt> to the state column, but does not persist it to the database
|
||||||
|
#
|
||||||
|
# foo = Foo.find(1)
|
||||||
|
# foo.aasm_current_state # => :opened
|
||||||
|
# foo.close
|
||||||
|
# foo.aasm_current_state # => :closed
|
||||||
|
# Foo.find(1).aasm_current_state # => :opened
|
||||||
|
# foo.save
|
||||||
|
# foo.aasm_current_state # => :closed
|
||||||
|
# Foo.find(1).aasm_current_state # => :closed
|
||||||
|
#
|
||||||
|
# NOTE: intended to be called from an event
|
||||||
|
def aasm_write_state_without_persistence(state)
|
||||||
|
write_attribute(self.class.aasm_column, state.to_s)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
module NamedScopeMethods
|
module NamedScopeMethods
|
||||||
|
|
|
@ -1,43 +1,67 @@
|
||||||
class DefaultState
|
class DefaultState
|
||||||
|
attr_accessor :transient_store
|
||||||
include AASM
|
include AASM
|
||||||
aasm do
|
aasm do
|
||||||
state :alpha, :initial => true
|
state :alpha, :initial => true
|
||||||
state :beta
|
state :beta
|
||||||
state :gamma
|
state :gamma
|
||||||
|
event :release do
|
||||||
|
transitions :from => [:alpha, :beta, :gamma], :to => :beta
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class ProvidedState
|
class ProvidedState
|
||||||
|
attr_accessor :transient_store
|
||||||
include AASM
|
include AASM
|
||||||
aasm do
|
aasm do
|
||||||
state :alpha, :initial => true
|
state :alpha, :initial => true
|
||||||
state :beta
|
state :beta
|
||||||
state :gamma
|
state :gamma
|
||||||
|
event :release do
|
||||||
|
transitions :from => [:alpha, :beta, :gamma], :to => :beta
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def aasm_read_state
|
def aasm_read_state
|
||||||
:beta
|
:beta
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def aasm_write_state(new_state)
|
||||||
|
@transient_store = new_state
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class PersistedState < ActiveRecord::Base
|
class PersistedState < ActiveRecord::Base
|
||||||
|
attr_accessor :transient_store
|
||||||
include AASM
|
include AASM
|
||||||
aasm do
|
aasm do
|
||||||
state :alpha, :initial => true
|
state :alpha, :initial => true
|
||||||
state :beta
|
state :beta
|
||||||
state :gamma
|
state :gamma
|
||||||
|
event :release do
|
||||||
|
transitions :from => [:alpha, :beta, :gamma], :to => :beta
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class ProvidedAndPersistedState < ActiveRecord::Base
|
class ProvidedAndPersistedState < ActiveRecord::Base
|
||||||
|
attr_accessor :transient_store
|
||||||
include AASM
|
include AASM
|
||||||
aasm do
|
aasm do
|
||||||
state :alpha, :initial => true
|
state :alpha, :initial => true
|
||||||
state :beta
|
state :beta
|
||||||
state :gamma
|
state :gamma
|
||||||
|
event :release do
|
||||||
|
transitions :from => [:alpha, :beta, :gamma], :to => :beta
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def aasm_read_state
|
def aasm_read_state
|
||||||
:gamma
|
:gamma
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def aasm_write_state(new_state)
|
||||||
|
@transient_store = new_state
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
require 'models/active_record/api.rb'
|
require 'models/active_record/api.rb'
|
||||||
|
|
||||||
describe "retrieving the current state" do
|
describe "reading the current state" do
|
||||||
it "uses the AASM default" do
|
it "uses the AASM default" do
|
||||||
DefaultState.new.aasm.current_state.should eql :alpha
|
DefaultState.new.aasm.current_state.should eql :alpha
|
||||||
end
|
end
|
||||||
|
@ -18,3 +18,29 @@ describe "retrieving the current state" do
|
||||||
ProvidedAndPersistedState.new.aasm.current_state.should eql :gamma
|
ProvidedAndPersistedState.new.aasm.current_state.should eql :gamma
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "writing the current state" do
|
||||||
|
it "uses the AASM default" do
|
||||||
|
o = DefaultState.new
|
||||||
|
o.release!
|
||||||
|
o.transient_store.should be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it "uses the provided method" do
|
||||||
|
o = ProvidedState.new
|
||||||
|
o.release!
|
||||||
|
o.transient_store.should eql :beta
|
||||||
|
end
|
||||||
|
|
||||||
|
it "uses the persistence storage" do
|
||||||
|
o = PersistedState.new
|
||||||
|
o.release!
|
||||||
|
o.transient_store.should be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it "uses the provided method even if persisted" do
|
||||||
|
o = ProvidedAndPersistedState.new
|
||||||
|
o.release!
|
||||||
|
o.transient_store.should eql :beta
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
@ -18,7 +18,6 @@ describe "class methods for classes without own read or write state" do
|
||||||
let(:klass) {Gate}
|
let(:klass) {Gate}
|
||||||
it_should_behave_like "aasm model"
|
it_should_behave_like "aasm model"
|
||||||
it "should include all persistence mixins" do
|
it "should include all persistence mixins" do
|
||||||
klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::WriteState)
|
|
||||||
klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence)
|
klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -27,7 +26,6 @@ describe "class methods for classes with own write state" do
|
||||||
let(:klass) {Writer}
|
let(:klass) {Writer}
|
||||||
it_should_behave_like "aasm model"
|
it_should_behave_like "aasm model"
|
||||||
it "should include include all persistence mixins but write state" do
|
it "should include include all persistence mixins but write state" do
|
||||||
klass.included_modules.should_not be_include(AASM::Persistence::ActiveRecordPersistence::WriteState)
|
|
||||||
klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence)
|
klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -36,7 +34,6 @@ describe "class methods for classes without persistence" do
|
||||||
let(:klass) {Transient}
|
let(:klass) {Transient}
|
||||||
it_should_behave_like "aasm model"
|
it_should_behave_like "aasm model"
|
||||||
it "should include all mixins but persistence" do
|
it "should include all mixins but persistence" do
|
||||||
klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::WriteState)
|
|
||||||
klass.included_modules.should_not be_include(AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence)
|
klass.included_modules.should_not be_include(AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue