mirror of
https://github.com/aasm/aasm
synced 2023-03-27 23:22:41 -04:00
may configure to not allow direct assignment for persisted AASM models #53
This commit is contained in:
parent
887a1658da
commit
163859caef
7 changed files with 80 additions and 7 deletions
|
@ -2,6 +2,7 @@
|
|||
|
||||
## 4.0.0 (not yet released)
|
||||
|
||||
* may configure to not allow direct assignment for persisted AASM models (see [issue #53](https://github.com/aasm/aasm/issues/53))
|
||||
* **DSL change**: callbacks don't require `to_state` parameter anymore, but still support it
|
||||
(closing issues
|
||||
[#11](https://github.com/aasm/aasm/issues/11),
|
||||
|
|
28
README.md
28
README.md
|
@ -278,6 +278,34 @@ class Job < ActiveRecord::Base
|
|||
end
|
||||
```
|
||||
|
||||
If you want to make sure that the _AASM_ column for storing the state is not directly assigned,
|
||||
configure _AASM_ to not allow direct assignment, like this:
|
||||
|
||||
```ruby
|
||||
class Job < ActiveRecord::Base
|
||||
include AASM
|
||||
|
||||
aasm :no_direct_assignment => true do
|
||||
state :sleeping, :initial => true
|
||||
state :running
|
||||
|
||||
event :run do
|
||||
transitions :from => :sleeping, :to => :running
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
```
|
||||
|
||||
resulting in this:
|
||||
|
||||
```ruby
|
||||
job = Job.create
|
||||
job.aasm_state # => 'sleeping'
|
||||
job.aasm_state = :running # => raises AASM::NoDirectAssignmentError
|
||||
job.aasm_state # => 'sleeping'
|
||||
```
|
||||
|
||||
### Sequel
|
||||
|
||||
AASM also supports [Sequel](http://sequel.jeremyevans.net/) besides _ActiveRecord_ and _Mongoid_.
|
||||
|
|
|
@ -4,7 +4,7 @@ module AASM
|
|||
def initialize(clazz, options={}, &block)
|
||||
@clazz = clazz
|
||||
@state_machine = AASM::StateMachine[@clazz]
|
||||
@state_machine.config.column = options[:column].to_sym if options[:column]
|
||||
@state_machine.config.column ||= (options[:column] || :aasm_state).to_sym
|
||||
@options = options
|
||||
|
||||
# let's cry if the transition is invalid
|
||||
|
@ -13,11 +13,21 @@ module AASM
|
|||
# create named scopes for each state
|
||||
configure :create_scopes, true
|
||||
|
||||
# don't store any new state if the model is invalid
|
||||
# don't store any new state if the model is invalid (in ActiveRecord)
|
||||
configure :skip_validation_on_save, false
|
||||
|
||||
# use requires_new for nested transactions
|
||||
# use requires_new for nested transactions (in ActiveRecord)
|
||||
configure :requires_new_transaction, true
|
||||
|
||||
# set to true to forbid direct assignment of aasm_state column (in ActiveRecord)
|
||||
configure :no_direct_assignment, false
|
||||
|
||||
|
||||
if @state_machine.config.no_direct_assignment
|
||||
@clazz.send(:define_method, "#{@state_machine.config.column}=") do |state_name|
|
||||
raise AASM::NoDirectAssignmentError.new('direct assignment of AASM column has been disabled (see AASM configuration for this class)')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def initial_state(new_initial_state=nil)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
module AASM
|
||||
class InvalidTransition < RuntimeError; end
|
||||
class UndefinedState < RuntimeError; end
|
||||
class NoDirectAssignmentError < RuntimeError; end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
ActiveRecord::Migration.suppress_messages do
|
||||
%w{gates readers writers transients simples simple_new_dsls no_scopes thieves localizer_test_models persisted_states provided_and_persisted_states}.each do |table_name|
|
||||
%w{gates readers writers transients simples simple_new_dsls no_scopes no_direct_assignments thieves localizer_test_models persisted_states provided_and_persisted_states}.each do |table_name|
|
||||
ActiveRecord::Migration.create_table table_name, :force => true do |t|
|
||||
t.string "aasm_state"
|
||||
end
|
||||
|
|
|
@ -48,7 +48,22 @@ end
|
|||
class NoScope < ActiveRecord::Base
|
||||
include AASM
|
||||
aasm :create_scopes => false do
|
||||
state :ignored_scope
|
||||
state :pending, :initial => true
|
||||
state :running
|
||||
event :run do
|
||||
transitions :from => :pending, :to => :running
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class NoDirectAssignment < ActiveRecord::Base
|
||||
include AASM
|
||||
aasm :no_direct_assignment => true do
|
||||
state :pending, :initial => true
|
||||
state :running
|
||||
event :run do
|
||||
transitions :from => :pending, :to => :running
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -93,10 +93,28 @@ describe "named scopes with the new DSL" do
|
|||
end
|
||||
|
||||
it "does not create scopes if requested" do
|
||||
expect(NoScope).not_to respond_to(:ignored_scope)
|
||||
expect(NoScope).not_to respond_to(:pending)
|
||||
end
|
||||
|
||||
end
|
||||
end # scopes
|
||||
|
||||
describe "direct assignment" do
|
||||
it "is allowed by default" do
|
||||
obj = NoScope.create
|
||||
expect(obj.aasm_state.to_sym).to eql :pending
|
||||
|
||||
obj.aasm_state = :running
|
||||
expect(obj.aasm_state.to_sym).to eql :running
|
||||
end
|
||||
|
||||
it "is forbidden if configured" do
|
||||
obj = NoDirectAssignment.create
|
||||
expect(obj.aasm_state.to_sym).to eql :pending
|
||||
|
||||
expect {obj.aasm_state = :running}.to raise_error(AASM::NoDirectAssignmentError)
|
||||
expect(obj.aasm_state.to_sym).to eql :pending
|
||||
end
|
||||
end # direct assignment
|
||||
|
||||
describe 'initial states' do
|
||||
|
||||
|
|
Loading…
Reference in a new issue