mirror of
https://github.com/aasm/aasm
synced 2023-03-27 23:22:41 -04:00
Implement whiny persistence so that transition!
will raise by default, mirroring ActiveRecord's behavior.
@PragTob's suggestion from https://github.com/aasm/aasm/issues/262.
This commit is contained in:
parent
a26b2f3b03
commit
5739f92219
8 changed files with 98 additions and 18 deletions
|
@ -23,6 +23,9 @@ module AASM
|
|||
# don't store any new state if the model is invalid (in ActiveRecord)
|
||||
configure :skip_validation_on_save, false
|
||||
|
||||
# raise if the model is invalid (in ActiveRecord)
|
||||
configure :whiny_persistence, true
|
||||
|
||||
# use requires_new for nested transactions (in ActiveRecord)
|
||||
configure :requires_new_transaction, true
|
||||
|
||||
|
|
|
@ -9,7 +9,10 @@ module AASM
|
|||
# for all persistence layers: create named scopes for each state
|
||||
attr_accessor :create_scopes
|
||||
|
||||
# for ActiveRecord: don't store any new state if the model is invalid
|
||||
# for ActiveRecord: when the model is invalid, true -> raise, false -> return false
|
||||
attr_accessor :whiny_persistence
|
||||
|
||||
# for ActiveRecord: store the new state even if the model is invalid and return true
|
||||
attr_accessor :skip_validation_on_save
|
||||
|
||||
# for ActiveRecord: use requires_new for nested transactions?
|
||||
|
|
|
@ -76,7 +76,12 @@ module AASM
|
|||
self.save
|
||||
end
|
||||
|
||||
success ? true : aasm_rollback(name, old_value)
|
||||
unless success
|
||||
aasm_rollback(name, old_value)
|
||||
raise ActiveRecord::RecordInvalid.new(self) if aasm_whiny_persistence(name)
|
||||
end
|
||||
|
||||
success
|
||||
end
|
||||
|
||||
# Writes <tt>state</tt> to the state column, but does not persist it to the database
|
||||
|
@ -130,6 +135,10 @@ module AASM
|
|||
AASM::StateMachineStore.fetch(self.class, true).machine(state_machine_name).config.skip_validation_on_save
|
||||
end
|
||||
|
||||
def aasm_whiny_persistence(state_machine_name)
|
||||
AASM::StateMachineStore.fetch(self.class, true).machine(state_machine_name).config.whiny_persistence
|
||||
end
|
||||
|
||||
def aasm_write_attribute(state, name=:default)
|
||||
write_attribute(self.class.aasm(name).attribute_name, aasm_raw_attribute_value(state, name))
|
||||
end
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
module AASM
|
||||
VERSION = "4.10.1"
|
||||
VERSION = "5.0.0"
|
||||
end
|
||||
|
|
|
@ -17,7 +17,7 @@ ActiveRecord::Migration.suppress_messages do
|
|||
t.string "right"
|
||||
end
|
||||
|
||||
%w(validators multiple_validators).each do |table_name|
|
||||
%w(validators multiple_validators workers invalid_persistors multiple_invalid_persistors silent_persistors multiple_silent_persistors).each do |table_name|
|
||||
ActiveRecord::Migration.create_table table_name, :force => true do |t|
|
||||
t.string "name"
|
||||
t.string "status"
|
||||
|
@ -32,20 +32,6 @@ ActiveRecord::Migration.suppress_messages do
|
|||
end
|
||||
end
|
||||
|
||||
ActiveRecord::Migration.create_table "workers", :force => true do |t|
|
||||
t.string "name"
|
||||
t.string "status"
|
||||
end
|
||||
|
||||
ActiveRecord::Migration.create_table "invalid_persistors", :force => true do |t|
|
||||
t.string "name"
|
||||
t.string "status"
|
||||
end
|
||||
ActiveRecord::Migration.create_table "multiple_invalid_persistors", :force => true do |t|
|
||||
t.string "name"
|
||||
t.string "status"
|
||||
end
|
||||
|
||||
ActiveRecord::Migration.create_table "fathers", :force => true do |t|
|
||||
t.string "aasm_state"
|
||||
t.string "type"
|
||||
|
|
31
spec/models/silent_persistor.rb
Normal file
31
spec/models/silent_persistor.rb
Normal file
|
@ -0,0 +1,31 @@
|
|||
require 'active_record'
|
||||
|
||||
class SilentPersistor < ActiveRecord::Base
|
||||
include AASM
|
||||
aasm :column => :status, :whiny_persistence => false do
|
||||
state :sleeping, :initial => true
|
||||
state :running
|
||||
event :run do
|
||||
transitions :to => :running, :from => :sleeping
|
||||
end
|
||||
event :sleep do
|
||||
transitions :to => :sleeping, :from => :running
|
||||
end
|
||||
end
|
||||
validates_presence_of :name
|
||||
end
|
||||
|
||||
class MultipleSilentPersistor < ActiveRecord::Base
|
||||
include AASM
|
||||
aasm :left, :column => :status, :whiny_persistence => false do
|
||||
state :sleeping, :initial => true
|
||||
state :running
|
||||
event :run do
|
||||
transitions :to => :running, :from => :sleeping
|
||||
end
|
||||
event :sleep do
|
||||
transitions :to => :sleeping, :from => :running
|
||||
end
|
||||
end
|
||||
validates_presence_of :name
|
||||
end
|
|
@ -384,6 +384,30 @@ describe 'transitions with persistence' do
|
|||
expect(validator).to be_valid
|
||||
expect(validator).to be_sleeping
|
||||
|
||||
validator.name = nil
|
||||
expect(validator).not_to be_valid
|
||||
expect { validator.run! }.to raise_error(ActiveRecord::RecordInvalid)
|
||||
expect(validator).to be_sleeping
|
||||
|
||||
validator.reload
|
||||
expect(validator).not_to be_running
|
||||
expect(validator).to be_sleeping
|
||||
|
||||
validator.name = 'another name'
|
||||
expect(validator).to be_valid
|
||||
expect(validator.run!).to be_truthy
|
||||
expect(validator).to be_running
|
||||
|
||||
validator.reload
|
||||
expect(validator).to be_running
|
||||
expect(validator).not_to be_sleeping
|
||||
end
|
||||
|
||||
it 'should not store states for invalid models silently if configured' do
|
||||
validator = MultipleSilentPersistor.create(:name => 'name')
|
||||
expect(validator).to be_valid
|
||||
expect(validator).to be_sleeping
|
||||
|
||||
validator.name = nil
|
||||
expect(validator).not_to be_valid
|
||||
expect(validator.run!).to be_falsey
|
||||
|
|
|
@ -385,6 +385,30 @@ describe 'transitions with persistence' do
|
|||
expect(validator).to be_valid
|
||||
expect(validator).to be_sleeping
|
||||
|
||||
validator.name = nil
|
||||
expect(validator).not_to be_valid
|
||||
expect { validator.run! }.to raise_error(ActiveRecord::RecordInvalid)
|
||||
expect(validator).to be_sleeping
|
||||
|
||||
validator.reload
|
||||
expect(validator).not_to be_running
|
||||
expect(validator).to be_sleeping
|
||||
|
||||
validator.name = 'another name'
|
||||
expect(validator).to be_valid
|
||||
expect(validator.run!).to be_truthy
|
||||
expect(validator).to be_running
|
||||
|
||||
validator.reload
|
||||
expect(validator).to be_running
|
||||
expect(validator).not_to be_sleeping
|
||||
end
|
||||
|
||||
it 'should not store states for invalid models silently if configured' do
|
||||
validator = SilentPersistor.create(:name => 'name')
|
||||
expect(validator).to be_valid
|
||||
expect(validator).to be_sleeping
|
||||
|
||||
validator.name = nil
|
||||
expect(validator).not_to be_valid
|
||||
expect(validator.run!).to be_falsey
|
||||
|
|
Loading…
Reference in a new issue