mirror of
https://github.com/aasm/aasm
synced 2023-03-27 23:22:41 -04:00
allow configuring behavior of nested transactions #107
This commit is contained in:
parent
f6c903fae4
commit
ca7306d0bb
5 changed files with 58 additions and 8 deletions
|
@ -6,6 +6,7 @@
|
|||
|
||||
## 3.1.0 (not yet released)
|
||||
|
||||
* allow configuring behavior of nested transactions (see [issue #107](https://github.com/aasm/aasm/issues/107))
|
||||
* validating the current state (see [issue #95](https://github.com/aasm/aasm/issues/95), thanks to [@ivantsepp](https://github.com/ivantsepp))
|
||||
|
||||
## 3.0.26
|
||||
|
|
22
README.md
22
README.md
|
@ -339,6 +339,28 @@ class Job < ActiveRecord::Base
|
|||
end
|
||||
```
|
||||
|
||||
If you want to encapsulate state changes within an own transaction, the behavior
|
||||
of this nested transaction might be confusing. Take a look at
|
||||
[ActiveRecord Nested Transactions](http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html)
|
||||
if you want to know more about this. Nevertheless, AASM by default requires a new transaction
|
||||
`transaction(:requires_new => true)`. You can override this behavior by changing
|
||||
the configuration
|
||||
|
||||
```ruby
|
||||
class Job < ActiveRecord::Base
|
||||
include AASM
|
||||
|
||||
aasm :requires_new_transaction => false do
|
||||
...
|
||||
end
|
||||
|
||||
...
|
||||
end
|
||||
```
|
||||
|
||||
which then leads to `transaction(:requires_new => false)`, the Rails default.
|
||||
|
||||
|
||||
### Column name & migration
|
||||
|
||||
As a default AASM uses the column `aasm_state` to store the states. You can override
|
||||
|
|
|
@ -23,6 +23,12 @@ module AASM
|
|||
elsif @state_machine.config.skip_validation_on_save.nil?
|
||||
@state_machine.config.skip_validation_on_save = false # this is the default, so don't store any new state if the model is invalid
|
||||
end
|
||||
|
||||
if options.key?(:requires_new_transaction)
|
||||
@state_machine.config.requires_new_transaction = options[:requires_new_transaction]
|
||||
elsif @state_machine.config.requires_new_transaction.nil?
|
||||
@state_machine.config.requires_new_transaction = true # use requires_new for nested transactions
|
||||
end
|
||||
end
|
||||
|
||||
def initial_state(new_initial_state=nil)
|
||||
|
|
|
@ -138,7 +138,7 @@ module AASM
|
|||
end
|
||||
|
||||
def aasm_fire_event(name, options, *args, &block)
|
||||
success = self.class.transaction(:requires_new => true) do
|
||||
success = self.class.transaction(:requires_new => requires_new?) do
|
||||
super
|
||||
end
|
||||
|
||||
|
@ -150,6 +150,10 @@ module AASM
|
|||
success
|
||||
end
|
||||
|
||||
def requires_new?
|
||||
AASM::StateMachine[self.class].config.requires_new_transaction
|
||||
end
|
||||
|
||||
def aasm_validate_states
|
||||
unless AASM::StateMachine[self.class].config.skip_validation_on_save
|
||||
if aasm.current_state && !aasm.states.include?(aasm.current_state)
|
||||
|
|
|
@ -173,16 +173,33 @@ describe 'transitions with persistence' do
|
|||
expect(worker.reload.status).to eq('sleeping')
|
||||
end
|
||||
|
||||
it "should rollback all changes in nested transaction" do
|
||||
expect(transactor).to be_sleeping
|
||||
expect(worker.status).to eq('sleeping')
|
||||
context "nested transactions" do
|
||||
it "should rollback all changes in nested transaction" do
|
||||
expect(transactor).to be_sleeping
|
||||
expect(worker.status).to eq('sleeping')
|
||||
|
||||
Worker.transaction do
|
||||
expect { transactor.run! }.to raise_error(StandardError, 'failed on purpose')
|
||||
Worker.transaction do
|
||||
expect { transactor.run! }.to raise_error(StandardError, 'failed on purpose')
|
||||
end
|
||||
|
||||
expect(transactor).to be_running
|
||||
expect(worker.reload.status).to eq('sleeping')
|
||||
end
|
||||
|
||||
expect(transactor).to be_running
|
||||
expect(worker.reload.status).to eq('sleeping')
|
||||
it "should only rollback changes in the main transaction not the nested one" do
|
||||
# change configuration to not require new transaction
|
||||
AASM::StateMachine[Transactor].config.requires_new_transaction = false
|
||||
|
||||
expect(transactor).to be_sleeping
|
||||
expect(worker.status).to eq('sleeping')
|
||||
|
||||
Worker.transaction do
|
||||
expect { transactor.run! }.to raise_error(StandardError, 'failed on purpose')
|
||||
end
|
||||
|
||||
expect(transactor).to be_running
|
||||
expect(worker.reload.status).to eq('running')
|
||||
end
|
||||
end
|
||||
|
||||
describe "after_commit callback" do
|
||||
|
|
Loading…
Reference in a new issue