diff --git a/API b/API
index a83fa38..b9acad1 100644
--- a/API
+++ b/API
@@ -7,3 +7,13 @@ Overwrite method to read the current state
# retrieve the current state manually
end
end
+
+Overwrite method to write the current state
+
+ class MyClass
+ include AASM
+
+ def aasm_write_state
+ # store the current state manually
+ end
+ end
diff --git a/lib/aasm/aasm.rb b/lib/aasm/aasm.rb
index 1f6c013..b8d8d62 100644
--- a/lib/aasm/aasm.rb
+++ b/lib/aasm/aasm.rb
@@ -86,6 +86,11 @@ module AASM
aasm.enter_initial_state
end
+ # may be overwritten by persistence mixins
+ def aasm_write_state(new_state)
+ true
+ end
+
# deprecated
def aasm_current_state
# warn "#aasm_current_state is deprecated and will be removed in version 3.2.0; please use #aasm.state instead!"
diff --git a/lib/aasm/instance_base.rb b/lib/aasm/instance_base.rb
index 41f7339..e79352a 100644
--- a/lib/aasm/instance_base.rb
+++ b/lib/aasm/instance_base.rb
@@ -69,10 +69,7 @@ module AASM
end
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)
- end
+ save_success = @instance.aasm_write_state(state)
self.current_state = state if save_success
save_success
end
diff --git a/lib/aasm/persistence/active_record_persistence.rb b/lib/aasm/persistence/active_record_persistence.rb
index 544e17b..077f449 100644
--- a/lib/aasm/persistence/active_record_persistence.rb
+++ b/lib/aasm/persistence/active_record_persistence.rb
@@ -7,7 +7,6 @@ module AASM
# * includes InstanceMethods
#
# Unless the corresponding methods are already defined, it includes
- # * WriteState
# * WriteStateWithoutPersistence
#
# Adds
@@ -34,7 +33,6 @@ module AASM
base.send(:include, AASM::Persistence::Base)
base.extend AASM::Persistence::ActiveRecordPersistence::ClassMethods
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)
if ActiveRecord::VERSION::MAJOR >= 3
@@ -74,54 +72,6 @@ module AASM
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
- aasm.enter_initial_state if send(self.class.aasm_column).blank?
- end
-
- def aasm_fire_event(name, options, *args)
- transaction do
- super
- end
- end
-
- end
-
- module WriteStateWithoutPersistence
- # Writes state 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 state to the state column and persists it to the database
#
# foo = Foo.find(1)
@@ -147,6 +97,51 @@ module AASM
true
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
+ aasm.enter_initial_state if send(self.class.aasm_column).blank?
+ end
+
+ def aasm_fire_event(name, options, *args)
+ transaction do
+ super
+ end
+ end
+ end # InstanceMethods
+
+ module WriteStateWithoutPersistence
+ # Writes state 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
diff --git a/lib/aasm/persistence/mongoid_persistence.rb b/lib/aasm/persistence/mongoid_persistence.rb
index f4f10b0..a6ae33e 100644
--- a/lib/aasm/persistence/mongoid_persistence.rb
+++ b/lib/aasm/persistence/mongoid_persistence.rb
@@ -7,7 +7,6 @@ module AASM
# * includes InstanceMethods
#
# Unless the corresponding methods are already defined, it includes
- # * WriteState
# * WriteStateWithoutPersistence
#
# Adds
@@ -36,7 +35,6 @@ module AASM
base.send(:include, AASM::Persistence::Base)
base.extend AASM::Persistence::MongoidPersistence::ClassMethods
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)
# Mongoid's Validatable gem dependency goes not have a before_validation_on_xxx hook yet.
@@ -68,48 +66,6 @@ module AASM
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 state 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 state to the state column and persists it to the database
# using update_attribute (which bypasses validation)
#
@@ -131,6 +87,45 @@ module AASM
true
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 state 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 NamedScopeMethods
diff --git a/spec/models/active_record/api.rb b/spec/models/active_record/api.rb
index 7b4f39f..082e9ea 100644
--- a/spec/models/active_record/api.rb
+++ b/spec/models/active_record/api.rb
@@ -1,43 +1,67 @@
class DefaultState
+ attr_accessor :transient_store
include AASM
aasm do
state :alpha, :initial => true
state :beta
state :gamma
+ event :release do
+ transitions :from => [:alpha, :beta, :gamma], :to => :beta
+ end
end
end
class ProvidedState
+ attr_accessor :transient_store
include AASM
aasm do
state :alpha, :initial => true
state :beta
state :gamma
+ event :release do
+ transitions :from => [:alpha, :beta, :gamma], :to => :beta
+ end
end
def aasm_read_state
:beta
end
+
+ def aasm_write_state(new_state)
+ @transient_store = new_state
+ end
end
class PersistedState < ActiveRecord::Base
+ attr_accessor :transient_store
include AASM
aasm do
state :alpha, :initial => true
state :beta
state :gamma
+ event :release do
+ transitions :from => [:alpha, :beta, :gamma], :to => :beta
+ end
end
end
class ProvidedAndPersistedState < ActiveRecord::Base
+ attr_accessor :transient_store
include AASM
aasm do
state :alpha, :initial => true
state :beta
state :gamma
+ event :release do
+ transitions :from => [:alpha, :beta, :gamma], :to => :beta
+ end
end
def aasm_read_state
:gamma
end
+
+ def aasm_write_state(new_state)
+ @transient_store = new_state
+ end
end
diff --git a/spec/unit/api_spec.rb b/spec/unit/api_spec.rb
index 7768203..55a08d9 100644
--- a/spec/unit/api_spec.rb
+++ b/spec/unit/api_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
require 'models/active_record/api.rb'
-describe "retrieving the current state" do
+describe "reading the current state" do
it "uses the AASM default" do
DefaultState.new.aasm.current_state.should eql :alpha
end
@@ -18,3 +18,29 @@ describe "retrieving the current state" do
ProvidedAndPersistedState.new.aasm.current_state.should eql :gamma
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
diff --git a/spec/unit/persistence/active_record_persistence_spec.rb b/spec/unit/persistence/active_record_persistence_spec.rb
index 2e2c7c6..9d73811 100644
--- a/spec/unit/persistence/active_record_persistence_spec.rb
+++ b/spec/unit/persistence/active_record_persistence_spec.rb
@@ -18,7 +18,6 @@ describe "class methods for classes without own read or write state" do
let(:klass) {Gate}
it_should_behave_like "aasm model"
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)
end
end
@@ -27,7 +26,6 @@ describe "class methods for classes with own write state" do
let(:klass) {Writer}
it_should_behave_like "aasm model"
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)
end
end
@@ -36,7 +34,6 @@ describe "class methods for classes without persistence" do
let(:klass) {Transient}
it_should_behave_like "aasm model"
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)
end
end