aasm 4.2.0 → 4.3.0

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.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -1
  3. data/Gemfile +2 -2
  4. data/PLANNED_CHANGES.md +24 -4
  5. data/README.md +75 -5
  6. data/lib/aasm/aasm.rb +50 -36
  7. data/lib/aasm/base.rb +36 -18
  8. data/lib/aasm/core/event.rb +6 -5
  9. data/lib/aasm/core/state.rb +3 -2
  10. data/lib/aasm/core/transition.rb +5 -4
  11. data/lib/aasm/errors.rb +7 -4
  12. data/lib/aasm/instance_base.rb +14 -13
  13. data/lib/aasm/localizer.rb +1 -1
  14. data/lib/aasm/persistence/active_record_persistence.rb +41 -66
  15. data/lib/aasm/persistence/base.rb +7 -7
  16. data/lib/aasm/persistence/mongo_mapper_persistence.rb +34 -51
  17. data/lib/aasm/persistence/mongoid_persistence.rb +15 -36
  18. data/lib/aasm/persistence/plain_persistence.rb +8 -7
  19. data/lib/aasm/persistence/sequel_persistence.rb +12 -10
  20. data/lib/aasm/state_machine.rb +11 -6
  21. data/lib/aasm/version.rb +1 -1
  22. data/spec/database.rb +27 -1
  23. data/spec/models/active_record/basic_active_record_two_state_machines_example.rb +25 -0
  24. data/spec/models/active_record/complex_active_record_example.rb +33 -0
  25. data/spec/models/active_record/derivate_new_dsl.rb +4 -0
  26. data/spec/models/active_record/false_state.rb +18 -0
  27. data/spec/models/active_record/gate.rb +20 -0
  28. data/spec/models/active_record/no_direct_assignment.rb +11 -0
  29. data/spec/models/active_record/no_scope.rb +11 -0
  30. data/spec/models/active_record/provided_and_persisted_state.rb +3 -3
  31. data/spec/models/active_record/simple_new_dsl.rb +9 -0
  32. data/spec/models/active_record/thief.rb +15 -0
  33. data/spec/models/active_record/with_enum.rb +20 -0
  34. data/spec/models/active_record/with_false_enum.rb +16 -0
  35. data/spec/models/active_record/with_true_enum.rb +20 -0
  36. data/spec/models/basic_two_state_machines_example.rb +25 -0
  37. data/spec/models/callbacks/basic_multiple.rb +75 -0
  38. data/spec/models/callbacks/guard_within_block_multiple.rb +66 -0
  39. data/spec/models/callbacks/multiple_transitions_transition_guard_multiple.rb +65 -0
  40. data/spec/models/callbacks/private_method_multiple.rb +44 -0
  41. data/spec/models/callbacks/with_args_multiple.rb +61 -0
  42. data/spec/models/callbacks/{with_state_args.rb → with_state_arg.rb} +0 -0
  43. data/spec/models/callbacks/with_state_arg_multiple.rb +26 -0
  44. data/spec/models/complex_example.rb +134 -0
  45. data/spec/models/conversation.rb +47 -1
  46. data/spec/models/foo.rb +57 -0
  47. data/spec/models/foo_callback_multiple.rb +45 -0
  48. data/spec/models/guardian_multiple.rb +48 -0
  49. data/spec/models/initial_state_proc.rb +16 -0
  50. data/spec/models/invalid_persistor.rb +15 -0
  51. data/spec/models/mongo_mapper/complex_mongo_mapper_example.rb +37 -0
  52. data/spec/models/mongo_mapper/no_scope_mongo_mapper.rb +11 -0
  53. data/spec/models/mongo_mapper/simple_mongo_mapper.rb +12 -0
  54. data/spec/models/mongo_mapper/simple_new_dsl_mongo_mapper.rb +13 -0
  55. data/spec/models/mongoid/complex_mongoid_example.rb +37 -0
  56. data/spec/models/mongoid/no_scope_mongoid.rb +11 -0
  57. data/spec/models/mongoid/simple_mongoid.rb +12 -0
  58. data/spec/models/mongoid/simple_new_dsl_mongoid.rb +13 -0
  59. data/spec/models/no_initial_state.rb +13 -0
  60. data/spec/models/parametrised_event.rb +1 -1
  61. data/spec/models/parametrised_event_multiple.rb +29 -0
  62. data/spec/models/provided_state.rb +3 -3
  63. data/spec/models/sequel/complex_sequel_example.rb +45 -0
  64. data/spec/models/sequel/sequel_multiple.rb +25 -0
  65. data/spec/models/sequel/sequel_simple.rb +25 -0
  66. data/spec/models/simple_multiple_example.rb +30 -0
  67. data/spec/models/sub_class.rb +4 -0
  68. data/spec/models/sub_class_with_more_states.rb +11 -0
  69. data/spec/models/super_class.rb +28 -0
  70. data/spec/models/transactor.rb +27 -0
  71. data/spec/models/valid_state_name.rb +12 -0
  72. data/spec/models/validator.rb +39 -0
  73. data/spec/unit/basic_two_state_machines_example_spec.rb +10 -0
  74. data/spec/unit/callback_multiple_spec.rb +295 -0
  75. data/spec/unit/callbacks_spec.rb +1 -1
  76. data/spec/unit/complex_multiple_example_spec.rb +99 -0
  77. data/spec/unit/edge_cases_spec.rb +16 -0
  78. data/spec/unit/event_multiple_spec.rb +73 -0
  79. data/spec/unit/event_spec.rb +11 -6
  80. data/spec/unit/guard_multiple_spec.rb +60 -0
  81. data/spec/unit/initial_state_multiple_spec.rb +15 -0
  82. data/spec/unit/inspection_multiple_spec.rb +201 -0
  83. data/spec/unit/persistence/active_record_persistence_multiple_spec.rb +560 -0
  84. data/spec/unit/persistence/active_record_persistence_spec.rb +17 -12
  85. data/spec/unit/persistence/mongo_mapper_persistence_multiple_spec.rb +146 -0
  86. data/spec/unit/persistence/{mongo_mapper_persistance_spec.rb → mongo_mapper_persistence_spec.rb} +7 -49
  87. data/spec/unit/persistence/mongoid_persistence_multiple_spec.rb +127 -0
  88. data/spec/unit/persistence/mongoid_persistence_spec.rb +79 -0
  89. data/spec/unit/persistence/sequel_persistence_multiple_spec.rb +153 -0
  90. data/spec/unit/persistence/sequel_persistence_spec.rb +7 -24
  91. data/spec/unit/reloading_spec.rb +1 -1
  92. data/spec/unit/simple_multiple_example_spec.rb +63 -0
  93. data/spec/unit/state_spec.rb +3 -1
  94. data/spec/unit/subclassing_multiple_spec.rb +39 -0
  95. data/spec/unit/transition_spec.rb +31 -22
  96. metadata +73 -9
  97. data/spec/unit/persistence/mongoid_persistance_spec.rb +0 -146
@@ -9,3 +9,15 @@ class SimpleMongoMapper
9
9
  state :next
10
10
  end
11
11
  end
12
+
13
+ class SimpleMongoMapperMultiple
14
+ include MongoMapper::Document
15
+ include AASM
16
+
17
+ key :status, String
18
+
19
+ aasm :left, column: :status do
20
+ state :unknown_scope
21
+ state :next
22
+ end
23
+ end
@@ -10,3 +10,16 @@ class SimpleNewDslMongoMapper
10
10
  state :next
11
11
  end
12
12
  end
13
+
14
+ class SimpleNewDslMongoMapperMultiple
15
+ include MongoMapper::Document
16
+ include AASM
17
+
18
+ key :status, String
19
+
20
+ aasm :left, :column => :status
21
+ aasm :left do
22
+ state :unknown_scope
23
+ state :next
24
+ end
25
+ end
@@ -0,0 +1,37 @@
1
+ class ComplexMongoidExample
2
+ include Mongoid::Document
3
+ include AASM
4
+
5
+ field :left, :type => String
6
+ field :right, :type => String
7
+
8
+ aasm :left, :column => 'left' do
9
+ state :one, :initial => true
10
+ state :two
11
+ state :three
12
+
13
+ event :increment do
14
+ transitions :from => :one, :to => :two
15
+ transitions :from => :two, :to => :three
16
+ end
17
+ event :reset do
18
+ transitions :from => :three, :to => :one
19
+ end
20
+ end
21
+
22
+ aasm :right, :column => 'right' do
23
+ state :alpha, :initial => true
24
+ state :beta
25
+ state :gamma
26
+
27
+ event :level_up do
28
+ transitions :from => :alpha, :to => :beta
29
+ transitions :from => :beta, :to => :gamma
30
+ end
31
+ event :level_down do
32
+ transitions :from => :gamma, :to => :beta
33
+ transitions :from => :beta, :to => :alpha
34
+ end
35
+ end
36
+
37
+ end
@@ -8,3 +8,14 @@ class NoScopeMongoid
8
8
  state :ignored_scope
9
9
  end
10
10
  end
11
+
12
+ class NoScopeMongoidMultiple
13
+ include Mongoid::Document
14
+ include AASM
15
+
16
+ field :status, :type => String
17
+
18
+ aasm :left, :create_scopes => false, :column => :status do
19
+ state :ignored_scope
20
+ end
21
+ end
@@ -9,3 +9,15 @@ class SimpleMongoid
9
9
  state :new
10
10
  end
11
11
  end
12
+
13
+ class SimpleMongoidMultiple
14
+ include Mongoid::Document
15
+ include AASM
16
+
17
+ field :status, :type => String
18
+
19
+ aasm :left, column: :status do
20
+ state :unknown_scope
21
+ state :new
22
+ end
23
+ end
@@ -10,3 +10,16 @@ class SimpleNewDslMongoid
10
10
  state :new
11
11
  end
12
12
  end
13
+
14
+ class SimpleNewDslMongoidMultiple
15
+ include Mongoid::Document
16
+ include AASM
17
+
18
+ field :status, :type => String
19
+
20
+ aasm :left, :column => :status
21
+ aasm :left do
22
+ state :unknown_scope, :initial => true
23
+ state :new
24
+ end
25
+ end
@@ -10,3 +10,16 @@ class NoInitialState
10
10
  end
11
11
  end
12
12
  end
13
+
14
+ class NoInitialStateMultiple
15
+ include AASM
16
+
17
+ aasm(:left) do
18
+ state :read
19
+ state :ended
20
+
21
+ event :foo do
22
+ transitions :to => :ended, :from => [:read]
23
+ end
24
+ end
25
+ end
@@ -18,7 +18,7 @@ class ParametrisedEvent
18
18
  end
19
19
  end
20
20
 
21
- def wear_clothes(shirt_color, trouser_type)
21
+ def wear_clothes(shirt_color, trouser_type=nil)
22
22
  end
23
23
 
24
24
  def condition_hair
@@ -0,0 +1,29 @@
1
+ class ParametrisedEventMultiple
2
+ include AASM
3
+ aasm(:left) do
4
+ state :sleeping, :initial => true
5
+ state :showering
6
+ state :working
7
+ state :dating
8
+ state :prettying_up
9
+
10
+ event :wakeup do
11
+ transitions :from => :sleeping, :to => [:showering, :working]
12
+ end
13
+
14
+ event :dress do
15
+ transitions :from => :sleeping, :to => :working, :after => :wear_clothes
16
+ transitions :from => :showering, :to => [:working, :dating], :after => Proc.new { |*args| wear_clothes(*args) }
17
+ transitions :from => :showering, :to => :prettying_up, :after => [:condition_hair, :fix_hair]
18
+ end
19
+ end
20
+
21
+ def wear_clothes(shirt_color, trouser_type=nil)
22
+ end
23
+
24
+ def condition_hair
25
+ end
26
+
27
+ def fix_hair
28
+ end
29
+ end
@@ -10,15 +10,15 @@ class ProvidedState
10
10
  end
11
11
  end
12
12
 
13
- def aasm_read_state
13
+ def aasm_read_state(*args)
14
14
  :beta
15
15
  end
16
16
 
17
- def aasm_write_state(new_state)
17
+ def aasm_write_state(new_state, *args)
18
18
  @persisted_store = new_state
19
19
  end
20
20
 
21
- def aasm_write_state_without_persistence(new_state)
21
+ def aasm_write_state_without_persistence(new_state, *args)
22
22
  @transient_store = new_state
23
23
  end
24
24
  end
@@ -0,0 +1,45 @@
1
+ db = Sequel.connect(SEQUEL_DB)
2
+
3
+ # if you want to see the statements while running the spec enable the following line
4
+ # db.loggers << Logger.new($stderr)
5
+ db.create_table(:complex_sequel_examples) do
6
+ primary_key :id
7
+ String :left
8
+ String :right
9
+ end
10
+
11
+ class ComplexSequelExample < Sequel::Model(db)
12
+ set_dataset(:complex_sequel_examples)
13
+
14
+ include AASM
15
+
16
+ aasm :left, :column => 'left' do
17
+ state :one, :initial => true
18
+ state :two
19
+ state :three
20
+
21
+ event :increment do
22
+ transitions :from => :one, :to => :two
23
+ transitions :from => :two, :to => :three
24
+ end
25
+ event :reset do
26
+ transitions :from => :three, :to => :one
27
+ end
28
+ end
29
+
30
+ aasm :right, :column => 'right' do
31
+ state :alpha, :initial => true
32
+ state :beta
33
+ state :gamma
34
+
35
+ event :level_up do
36
+ transitions :from => :alpha, :to => :beta
37
+ transitions :from => :beta, :to => :gamma
38
+ end
39
+ event :level_down do
40
+ transitions :from => :gamma, :to => :beta
41
+ transitions :from => :beta, :to => :alpha
42
+ end
43
+ end
44
+
45
+ end
@@ -0,0 +1,25 @@
1
+ db = Sequel.connect(SEQUEL_DB)
2
+
3
+ # if you want to see the statements while running the spec enable the following line
4
+ # db.loggers << Logger.new($stderr)
5
+ db.create_table(:multiples) do
6
+ primary_key :id
7
+ String :status
8
+ end
9
+
10
+ class SequelMultiple < Sequel::Model(db)
11
+ set_dataset(:multiples)
12
+ include AASM
13
+
14
+ attr_accessor :default
15
+
16
+ aasm :left, :column => :status
17
+ aasm :left do
18
+ state :alpha, :initial => true
19
+ state :beta
20
+ state :gamma
21
+ event :release do
22
+ transitions :from => [:alpha, :beta, :gamma], :to => :beta
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ db = Sequel.connect(SEQUEL_DB)
2
+
3
+ # if you want to see the statements while running the spec enable the following line
4
+ # db.loggers << Logger.new($stderr)
5
+ db.create_table(:simples) do
6
+ primary_key :id
7
+ String :status
8
+ end
9
+
10
+ class SequelSimple < Sequel::Model(db)
11
+ set_dataset(:simples)
12
+ include AASM
13
+
14
+ attr_accessor :default
15
+
16
+ aasm :column => :status
17
+ aasm do
18
+ state :alpha, :initial => true
19
+ state :beta
20
+ state :gamma
21
+ event :release do
22
+ transitions :from => [:alpha, :beta, :gamma], :to => :beta
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,30 @@
1
+ class SimpleMultipleExample
2
+ include AASM
3
+ aasm(:move) do
4
+ state :standing, :initial => true
5
+ state :walking
6
+ state :running
7
+
8
+ event :walk do
9
+ transitions :from => :standing, :to => :walking
10
+ end
11
+ event :run do
12
+ transitions :from => [:standing, :walking], :to => :running
13
+ end
14
+ event :hold do
15
+ transitions :from => [:walking, :running], :to => :standing
16
+ end
17
+ end
18
+
19
+ aasm(:work) do
20
+ state :sleeping, :initial => true
21
+ state :processing
22
+
23
+ event :start do
24
+ transitions :from => :sleeping, :to => :processing
25
+ end
26
+ event :stop do
27
+ transitions :from => :processing, :to => :sleeping
28
+ end
29
+ end
30
+ end
@@ -1,3 +1,7 @@
1
1
  require_relative 'super_class'
2
+
2
3
  class SubClass < SuperClass
3
4
  end
5
+
6
+ class SubClassMultiple < SuperClassMultiple
7
+ end
@@ -1,7 +1,18 @@
1
1
  require_relative 'super_class'
2
+
2
3
  class SubClassWithMoreStates < SuperClass
3
4
  include AASM
4
5
  aasm do
5
6
  state :foo
6
7
  end
7
8
  end
9
+
10
+ class SubClassWithMoreStatesMultiple < SuperClassMultiple
11
+ include AASM
12
+ aasm(:left) do
13
+ state :foo
14
+ end
15
+ aasm(:right) do
16
+ state :archived
17
+ end
18
+ end
@@ -16,3 +16,31 @@ class SuperClass
16
16
  end
17
17
  end
18
18
  end
19
+
20
+ class SuperClassMultiple
21
+ include AASM
22
+
23
+ aasm(:left) do
24
+ state :read
25
+ state :ended
26
+
27
+ event :foo do
28
+ transitions :to => :ended, :from => [:read]
29
+ end
30
+ end
31
+
32
+ aasm(:right) do
33
+ state :opened
34
+ state :closed
35
+
36
+ event :close do
37
+ transitions :to => :closed, :from => [:opened]
38
+ end
39
+ end
40
+
41
+ def update_state
42
+ if may_foo?
43
+ foo!
44
+ end
45
+ end
46
+ end
@@ -1,4 +1,5 @@
1
1
  require 'active_record'
2
+
2
3
  class Transactor < ActiveRecord::Base
3
4
 
4
5
  belongs_to :worker
@@ -24,3 +25,29 @@ private
24
25
  end
25
26
 
26
27
  end
28
+
29
+ class MultipleTransactor < ActiveRecord::Base
30
+
31
+ belongs_to :worker
32
+
33
+ include AASM
34
+ aasm :left, :column => :status do
35
+ state :sleeping, :initial => true
36
+ state :running, :before_enter => :start_worker, :after_enter => :fail
37
+
38
+ event :run do
39
+ transitions :to => :running, :from => :sleeping
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def start_worker
46
+ worker.update_attribute(:status, 'running')
47
+ end
48
+
49
+ def fail
50
+ raise StandardError.new('failed on purpose')
51
+ end
52
+
53
+ end
@@ -9,3 +9,15 @@ class ValidStateName
9
9
  end
10
10
  end
11
11
  end
12
+
13
+ class ValidStateNameMultiple
14
+ include AASM
15
+ aasm(:left) do
16
+ state :invalid, :initial => true
17
+ state :valid
18
+
19
+ event :valid do
20
+ transitions :to => :valid, :from => [:invalid]
21
+ end
22
+ end
23
+ end
@@ -38,3 +38,42 @@ class Validator < ActiveRecord::Base
38
38
  raise StandardError.new('failed on purpose')
39
39
  end
40
40
  end
41
+
42
+ class MultipleValidator < ActiveRecord::Base
43
+
44
+ include AASM
45
+ aasm :left, :column => :status do
46
+ state :sleeping, :initial => true
47
+ state :running
48
+ state :failed, :after_enter => :fail
49
+
50
+ event :run, :after_commit => :change_name! do
51
+ transitions :to => :running, :from => :sleeping
52
+ end
53
+ event :sleep do
54
+ after_commit do |name|
55
+ change_name_on_sleep name
56
+ end
57
+ transitions :to => :sleeping, :from => :running
58
+ end
59
+ event :fail do
60
+ transitions :to => :failed, :from => [:sleeping, :running]
61
+ end
62
+ end
63
+
64
+ validates_presence_of :name
65
+
66
+ def change_name!
67
+ self.name = "name changed"
68
+ save!
69
+ end
70
+
71
+ def change_name_on_sleep name
72
+ self.name = name
73
+ save!
74
+ end
75
+
76
+ def fail
77
+ raise StandardError.new('failed on purpose')
78
+ end
79
+ end