aasm 4.0.3 → 4.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +7 -7
- data/aasm.gemspec +5 -9
- data/lib/aasm.rb +13 -15
- data/lib/aasm/aasm.rb +0 -18
- data/lib/aasm/base.rb +1 -1
- data/lib/aasm/{event.rb → core/event.rb} +3 -3
- data/lib/aasm/{state.rb → core/state.rb} +1 -1
- data/lib/aasm/{transition.rb → core/transition.rb} +1 -1
- data/lib/aasm/persistence.rb +17 -11
- data/lib/aasm/persistence/active_record_persistence.rb +6 -9
- data/lib/aasm/persistence/mongoid_persistence.rb +4 -2
- data/lib/aasm/persistence/plain_persistence.rb +24 -0
- data/lib/aasm/persistence/sequel_persistence.rb +2 -0
- data/lib/aasm/state_machine.rb +1 -1
- data/lib/aasm/version.rb +1 -1
- data/spec/database.rb +5 -1
- data/spec/models/callbacks/basic.rb +62 -0
- data/spec/models/callbacks/guard_within_block.rb +66 -0
- data/spec/models/callbacks/with_args.rb +45 -0
- data/spec/models/callbacks/with_state_args.rb +26 -0
- data/spec/models/persistence.rb +61 -1
- data/spec/unit/callbacks_spec.rb +35 -32
- data/spec/unit/event_spec.rb +6 -6
- data/spec/unit/memory_leak_spec.rb +12 -12
- data/spec/unit/persistence/active_record_persistence_spec.rb +12 -36
- data/spec/unit/state_spec.rb +2 -2
- data/spec/unit/transition_spec.rb +23 -23
- metadata +20 -51
- data/spec/models/callback_new_dsl.rb +0 -129
- data/spec/models/guard_within_block.rb +0 -64
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4f80e2467a731eee5737b3c74cfb3d4236be0df5
|
4
|
+
data.tar.gz: 7175348561bd968b2208bb1a54b382dc4d72d2e8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4b435f505dc2a2f30302ac902fa1264d70f8c40f5d4101ac669dc8bac1ddddc34c9b67aca1ea5c899074814a3ef8fdb272c008ed10480c156bdaacd5adcb4a77
|
7
|
+
data.tar.gz: 50ac955db2fda8ca2bf711f0e2dcabf648996c021bb3921ace2793cef1ea71402407e00326674505e5c5bacf35d8b3d99f09d9acb8eedd7791fc6f3d6d022b6e
|
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,12 @@
|
|
5
5
|
* `aasm_column` has been removed. Use `aasm.attribute_name` instead
|
6
6
|
* `aasm_human_event_name` has been removed. Use `aasm.human_event_name` instead
|
7
7
|
|
8
|
+
## 4.0.4
|
9
|
+
|
10
|
+
* corrected callback order in README
|
11
|
+
* bugfix: initialize the aasm state column after initialization of the _ActiveRecord_ instance (see [issue #191](https://github.com/aasm/aasm/issues/191) for details)
|
12
|
+
* bugfix: avoid Rails autoloading conflicts (see [issue #137](https://github.com/aasm/aasm/issues/137) and [issue #139](https://github.com/aasm/aasm/issues/139) for details)
|
13
|
+
|
8
14
|
## 4.0.3
|
9
15
|
|
10
16
|
* bugfix: fire guards only once per transition, part 2 (see [issue #187](https://github.com/aasm/aasm/issues/187) for details)
|
data/README.md
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# AASM - Ruby state machines
|
2
2
|
|
3
|
-
|
3
|
+
[](http://badge.fury.io/rb/aasm)
|
4
4
|
[](https://travis-ci.org/aasm/aasm)
|
5
|
-
[](https://codeclimate.com/github/aasm/aasm)
|
6
|
+
[](https://coveralls.io/r/aasm/aasm?branch=master)
|
7
7
|
|
8
8
|
This package contains AASM, a library for adding finite state machines to Ruby classes.
|
9
9
|
|
@@ -145,11 +145,11 @@ begin
|
|
145
145
|
transition guards
|
146
146
|
old_state before_exit
|
147
147
|
old_state exit
|
148
|
+
transition after
|
148
149
|
new_state before_enter
|
149
150
|
new_state enter
|
150
|
-
|
151
|
-
|
152
|
-
event success # if persist successful
|
151
|
+
...update state...
|
152
|
+
event success # if persist successful
|
153
153
|
old_state after_exit
|
154
154
|
new_state after_enter
|
155
155
|
event after
|
@@ -172,7 +172,7 @@ Note that when passing arguments to a state transition, the first argument must
|
|
172
172
|
In case of an error during the event processing the error is rescued and passed to `:error`
|
173
173
|
callback, which can handle it or re-raise it for further propagation.
|
174
174
|
|
175
|
-
During the `:
|
175
|
+
During the transition's `:after` callback (and reliably only then) you can access the
|
176
176
|
originating state (the from-state) and the target state (the to state), like this:
|
177
177
|
|
178
178
|
```ruby
|
data/aasm.gemspec
CHANGED
@@ -13,20 +13,16 @@ Gem::Specification.new do |s|
|
|
13
13
|
s.date = Time.now
|
14
14
|
s.licenses = ["MIT"]
|
15
15
|
|
16
|
-
# s.add_development_dependency 'activerecord', '3.2.15'
|
17
|
-
# s.add_development_dependency 'activerecord', '4.0.1'
|
18
|
-
|
19
|
-
# s.add_development_dependency 'mongoid' if Gem::Version.create(RUBY_VERSION.dup) >= Gem::Version.create('1.9.3')
|
20
16
|
s.add_development_dependency 'rake'
|
21
17
|
s.add_development_dependency 'sdoc'
|
22
|
-
s.add_development_dependency 'rspec', '
|
23
|
-
|
24
|
-
#
|
25
|
-
s.add_development_dependency 'minitest'
|
18
|
+
s.add_development_dependency 'rspec', '>= 2.14', '< 2.99'
|
19
|
+
|
20
|
+
# debugging
|
26
21
|
# s.add_development_dependency 'debugger'
|
27
22
|
# s.add_development_dependency 'pry'
|
28
23
|
|
29
|
-
|
24
|
+
# test coverage
|
25
|
+
# s.add_development_dependency 'mime-types', '~> 1.25' # needed by coveralls (>= 2.0 needs Ruby >=1.9.2)
|
30
26
|
# s.add_development_dependency 'coveralls'
|
31
27
|
|
32
28
|
s.files = `git ls-files`.split("\n")
|
data/lib/aasm.rb
CHANGED
@@ -1,17 +1,15 @@
|
|
1
1
|
require 'ostruct'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
aasm
|
17
|
-
).each { |file| require File.join(File.dirname(__FILE__), 'aasm', file) }
|
3
|
+
require 'aasm/version'
|
4
|
+
require 'aasm/errors'
|
5
|
+
require 'aasm/configuration'
|
6
|
+
require 'aasm/base'
|
7
|
+
require 'aasm/dsl_helper'
|
8
|
+
require 'aasm/instance_base'
|
9
|
+
require 'aasm/core/transition'
|
10
|
+
require 'aasm/core/event'
|
11
|
+
require 'aasm/core/state'
|
12
|
+
require 'aasm/localizer'
|
13
|
+
require 'aasm/state_machine'
|
14
|
+
require 'aasm/persistence'
|
15
|
+
require 'aasm/aasm'
|
data/lib/aasm/aasm.rb
CHANGED
@@ -40,24 +40,6 @@ module AASM
|
|
40
40
|
@aasm ||= AASM::InstanceBase.new(self)
|
41
41
|
end
|
42
42
|
|
43
|
-
# may be overwritten by persistence mixins
|
44
|
-
def aasm_read_state
|
45
|
-
# all the following lines behave like @current_state ||= aasm.enter_initial_state
|
46
|
-
current = aasm.instance_variable_get("@current_state")
|
47
|
-
return current if current
|
48
|
-
aasm.instance_variable_set("@current_state", aasm.enter_initial_state)
|
49
|
-
end
|
50
|
-
|
51
|
-
# may be overwritten by persistence mixins
|
52
|
-
def aasm_write_state(new_state)
|
53
|
-
true
|
54
|
-
end
|
55
|
-
|
56
|
-
# may be overwritten by persistence mixins
|
57
|
-
def aasm_write_state_without_persistence(new_state)
|
58
|
-
true
|
59
|
-
end
|
60
|
-
|
61
43
|
private
|
62
44
|
|
63
45
|
# Takes args and a from state and removes the first
|
data/lib/aasm/base.rb
CHANGED
@@ -67,7 +67,7 @@ module AASM
|
|
67
67
|
|
68
68
|
# define an event
|
69
69
|
def event(name, options={}, &block)
|
70
|
-
@state_machine.events[name] = AASM::Event.new(name, options, &block)
|
70
|
+
@state_machine.events[name] = AASM::Core::Event.new(name, options, &block)
|
71
71
|
|
72
72
|
# an addition over standard aasm so that, before firing an event, you can ask
|
73
73
|
# may_event? and get back a boolean that tells you whether the guard method
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module AASM
|
1
|
+
module AASM::Core
|
2
2
|
class Event
|
3
3
|
include DslHelper
|
4
4
|
|
@@ -61,11 +61,11 @@ module AASM
|
|
61
61
|
if definitions # define new transitions
|
62
62
|
# Create a separate transition for each from-state to the given state
|
63
63
|
Array(definitions[:from]).each do |s|
|
64
|
-
@transitions << AASM::Transition.new(attach_event_guards(definitions.merge(:from => s.to_sym)), &block)
|
64
|
+
@transitions << AASM::Core::Transition.new(attach_event_guards(definitions.merge(:from => s.to_sym)), &block)
|
65
65
|
end
|
66
66
|
# Create a transition if :to is specified without :from (transitions from ANY state)
|
67
67
|
if @transitions.empty? && definitions[:to]
|
68
|
-
@transitions << AASM::Transition.new(attach_event_guards(definitions), &block)
|
68
|
+
@transitions << AASM::Core::Transition.new(attach_event_guards(definitions), &block)
|
69
69
|
end
|
70
70
|
end
|
71
71
|
@transitions
|
data/lib/aasm/persistence.rb
CHANGED
@@ -7,23 +7,29 @@ module AASM
|
|
7
7
|
hierarchy = base.ancestors.map {|klass| klass.to_s}
|
8
8
|
|
9
9
|
if hierarchy.include?("ActiveRecord::Base")
|
10
|
-
|
11
|
-
base.send(:include, AASM::Persistence::ActiveRecordPersistence)
|
10
|
+
include_persistence base, :active_record
|
12
11
|
elsif hierarchy.include?("Mongoid::Document")
|
13
|
-
|
14
|
-
base.send(:include, AASM::Persistence::MongoidPersistence)
|
12
|
+
include_persistence base, :mongoid
|
15
13
|
elsif hierarchy.include?("Sequel::Model")
|
16
|
-
|
17
|
-
|
14
|
+
include_persistence base, :sequel
|
15
|
+
else
|
16
|
+
include_persistence base, :plain
|
18
17
|
end
|
19
18
|
end
|
20
19
|
|
21
|
-
|
20
|
+
private
|
22
21
|
|
23
|
-
def
|
24
|
-
|
25
|
-
|
26
|
-
|
22
|
+
def include_persistence(base, type)
|
23
|
+
require File.join(File.dirname(__FILE__), 'persistence', "#{type}_persistence")
|
24
|
+
base.send(:include, constantize("AASM::Persistence::#{capitalize(type)}Persistence"))
|
25
|
+
end
|
26
|
+
|
27
|
+
def capitalize(string_or_symbol)
|
28
|
+
string_or_symbol.to_s.split('_').map {|segment| segment[0].upcase + segment[1..-1]}.join('')
|
29
|
+
end
|
30
|
+
|
31
|
+
def constantize(string)
|
32
|
+
instance_eval(string)
|
27
33
|
end
|
28
34
|
|
29
35
|
end # class << self
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require_relative 'base'
|
2
|
+
|
1
3
|
module AASM
|
2
4
|
module Persistence
|
3
5
|
module ActiveRecordPersistence
|
@@ -31,15 +33,10 @@ module AASM
|
|
31
33
|
base.extend AASM::Persistence::ActiveRecordPersistence::ClassMethods
|
32
34
|
base.send(:include, AASM::Persistence::ActiveRecordPersistence::InstanceMethods)
|
33
35
|
|
34
|
-
|
35
|
-
|
36
|
-
else
|
37
|
-
base.before_validation_on_create(:aasm_ensure_initial_state)
|
36
|
+
base.after_initialize do
|
37
|
+
aasm_ensure_initial_state
|
38
38
|
end
|
39
39
|
|
40
|
-
# ensure initial aasm state even when validations are skipped
|
41
|
-
base.before_create(:aasm_ensure_initial_state)
|
42
|
-
|
43
40
|
# ensure state is in the list of states
|
44
41
|
base.validate :aasm_validate_states
|
45
42
|
end
|
@@ -195,5 +192,5 @@ module AASM
|
|
195
192
|
end # InstanceMethods
|
196
193
|
|
197
194
|
end
|
198
|
-
end
|
199
|
-
end
|
195
|
+
end # Persistence
|
196
|
+
end # AASM
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module AASM
|
2
|
+
module Persistence
|
3
|
+
module PlainPersistence
|
4
|
+
|
5
|
+
def aasm_read_state
|
6
|
+
# all the following lines behave like @current_state ||= aasm.enter_initial_state
|
7
|
+
current = aasm.instance_variable_get("@current_state")
|
8
|
+
return current if current
|
9
|
+
aasm.instance_variable_set("@current_state", aasm.enter_initial_state)
|
10
|
+
end
|
11
|
+
|
12
|
+
# may be overwritten by persistence mixins
|
13
|
+
def aasm_write_state(new_state)
|
14
|
+
true
|
15
|
+
end
|
16
|
+
|
17
|
+
# may be overwritten by persistence mixins
|
18
|
+
def aasm_write_state_without_persistence(new_state)
|
19
|
+
true
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/aasm/state_machine.rb
CHANGED
data/lib/aasm/version.rb
CHANGED
data/spec/database.rb
CHANGED
@@ -1,10 +1,14 @@
|
|
1
1
|
ActiveRecord::Migration.suppress_messages do
|
2
|
-
%w{gates readers writers transients simples
|
2
|
+
%w{gates readers writers transients simples no_scopes no_direct_assignments thieves localizer_test_models persisted_states provided_and_persisted_states with_enums with_true_enums with_false_enums}.each do |table_name|
|
3
3
|
ActiveRecord::Migration.create_table table_name, :force => true do |t|
|
4
4
|
t.string "aasm_state"
|
5
5
|
end
|
6
6
|
end
|
7
7
|
|
8
|
+
ActiveRecord::Migration.create_table "simple_new_dsls", :force => true do |t|
|
9
|
+
t.string "status"
|
10
|
+
end
|
11
|
+
|
8
12
|
ActiveRecord::Migration.create_table "validators", :force => true do |t|
|
9
13
|
t.string "name"
|
10
14
|
t.string "status"
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Callbacks
|
2
|
+
class Basic
|
3
|
+
include AASM
|
4
|
+
|
5
|
+
def initialize(options={})
|
6
|
+
@fail_event_guard = options[:fail_event_guard]
|
7
|
+
@fail_transition_guard = options[:fail_transition_guard]
|
8
|
+
@log = options[:log]
|
9
|
+
end
|
10
|
+
|
11
|
+
aasm do
|
12
|
+
state :open, :initial => true,
|
13
|
+
:before_enter => :before_enter_open,
|
14
|
+
:enter => :enter_open,
|
15
|
+
:after_enter => :after_enter_open,
|
16
|
+
:before_exit => :before_exit_open,
|
17
|
+
:exit => :exit_open,
|
18
|
+
:after_exit => :after_exit_open
|
19
|
+
|
20
|
+
state :closed,
|
21
|
+
:before_enter => :before_enter_closed,
|
22
|
+
:enter => :enter_closed,
|
23
|
+
:after_enter => :after_enter_closed,
|
24
|
+
:before_exit => :before_exit_closed,
|
25
|
+
:exit => :exit_closed,
|
26
|
+
:after_exit => :after_exit_closed
|
27
|
+
|
28
|
+
event :close, :before => :before_event, :after => :after_event, :guard => :event_guard do
|
29
|
+
transitions :to => :closed, :from => [:open], :guard => :transition_guard, :after => :after_transition
|
30
|
+
end
|
31
|
+
|
32
|
+
event :open, :before => :before_event, :after => :after_event do
|
33
|
+
transitions :to => :open, :from => :closed
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def log(text)
|
38
|
+
puts text if @log
|
39
|
+
end
|
40
|
+
|
41
|
+
def before_enter_open; log('before_enter_open'); end
|
42
|
+
def enter_open; log('enter_open'); end
|
43
|
+
def before_exit_open; log('before_exit_open'); end
|
44
|
+
def after_enter_open; log('after_enter_open'); end
|
45
|
+
def exit_open; log('exit_open'); end
|
46
|
+
def after_exit_open; log('after_exit_open'); end
|
47
|
+
|
48
|
+
def before_enter_closed; log('before_enter_closed'); end
|
49
|
+
def enter_closed; log('enter_closed'); end
|
50
|
+
def before_exit_closed; log('before_exit_closed'); end
|
51
|
+
def exit_closed; log('exit_closed'); end
|
52
|
+
def after_enter_closed; log('after_enter_closed'); end
|
53
|
+
def after_exit_closed; log('after_exit_closed'); end
|
54
|
+
|
55
|
+
def event_guard; log('event_guard'); !@fail_event_guard; end
|
56
|
+
def transition_guard; log('transition_guard'); !@fail_transition_guard; end
|
57
|
+
def after_transition; log('after_transition'); end
|
58
|
+
|
59
|
+
def before_event; log('before_event'); end
|
60
|
+
def after_event; log('after_event'); end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Callbacks
|
2
|
+
class GuardWithinBlock
|
3
|
+
include AASM
|
4
|
+
|
5
|
+
def initialize(options={})
|
6
|
+
@fail_event_guard = options[:fail_event_guard]
|
7
|
+
@fail_transition_guard = options[:fail_transition_guard]
|
8
|
+
@log = options[:log]
|
9
|
+
end
|
10
|
+
|
11
|
+
aasm do
|
12
|
+
state :open, :initial => true,
|
13
|
+
:before_enter => :before_enter_open,
|
14
|
+
:enter => :enter_open,
|
15
|
+
:after_enter => :after_enter_open,
|
16
|
+
:before_exit => :before_exit_open,
|
17
|
+
:exit => :exit_open,
|
18
|
+
:after_exit => :after_exit_open
|
19
|
+
|
20
|
+
state :closed,
|
21
|
+
:before_enter => :before_enter_closed,
|
22
|
+
:enter => :enter_closed,
|
23
|
+
:after_enter => :after_enter_closed,
|
24
|
+
:before_exit => :before_exit_closed,
|
25
|
+
:exit => :exit_closed,
|
26
|
+
:after_exit => :after_exit_closed
|
27
|
+
|
28
|
+
event :close, :before => :before, :after => :after, :guard => :event_guard do
|
29
|
+
transitions :to => :closed, :from => [:open], :after => :transitioning do
|
30
|
+
guard do
|
31
|
+
transition_guard
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
event :open, :before => :before, :after => :after do
|
37
|
+
transitions :to => :open, :from => :closed
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def log(text)
|
42
|
+
puts text if @log
|
43
|
+
end
|
44
|
+
|
45
|
+
def before_enter_open; log('before_enter_open'); end
|
46
|
+
def enter_open; log('enter_open'); end
|
47
|
+
def before_exit_open; log('before_exit_open'); end
|
48
|
+
def after_enter_open; log('after_enter_open'); end
|
49
|
+
def exit_open; log('exit_open'); end
|
50
|
+
def after_exit_open; log('after_exit_open'); end
|
51
|
+
|
52
|
+
def before_enter_closed; log('before_enter_closed'); end
|
53
|
+
def enter_closed; log('enter_closed'); end
|
54
|
+
def before_exit_closed; log('before_exit_closed'); end
|
55
|
+
def exit_closed; log('exit_closed'); end
|
56
|
+
def after_enter_closed; log('after_enter_closed'); end
|
57
|
+
def after_exit_closed; log('after_exit_closed'); end
|
58
|
+
|
59
|
+
def event_guard; log('event_guard'); !@fail_event_guard; end
|
60
|
+
def transition_guard; log('transition_guard'); !@fail_transition_guard; end
|
61
|
+
def transitioning; log('transitioning'); end
|
62
|
+
|
63
|
+
def before; log('before'); end
|
64
|
+
def after; log('after'); end
|
65
|
+
end
|
66
|
+
end
|