aasm 4.11.1 → 4.12.1

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 (113) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +19 -16
  3. data/Appraisals +46 -0
  4. data/CHANGELOG.md +19 -0
  5. data/CONTRIBUTING.md +24 -0
  6. data/Gemfile +4 -21
  7. data/README.md +154 -39
  8. data/Rakefile +6 -1
  9. data/TESTING.md +25 -0
  10. data/aasm.gemspec +3 -0
  11. data/gemfiles/rails_3.2.gemfile +13 -0
  12. data/gemfiles/rails_4.0.gemfile +8 -9
  13. data/gemfiles/rails_4.2.gemfile +10 -9
  14. data/gemfiles/rails_4.2_mongoid_5.gemfile +5 -9
  15. data/gemfiles/rails_5.0.gemfile +8 -16
  16. data/lib/aasm/aasm.rb +9 -3
  17. data/lib/aasm/base.rb +11 -1
  18. data/lib/aasm/configuration.rb +4 -0
  19. data/lib/aasm/core/event.rb +18 -4
  20. data/lib/aasm/core/state.rb +7 -0
  21. data/lib/aasm/core/transition.rb +10 -1
  22. data/lib/aasm/instance_base.rb +0 -2
  23. data/lib/aasm/minitest/allow_event.rb +13 -0
  24. data/lib/aasm/minitest/allow_transition_to.rb +13 -0
  25. data/lib/aasm/minitest/have_state.rb +13 -0
  26. data/lib/aasm/minitest/transition_from.rb +21 -0
  27. data/lib/aasm/minitest.rb +5 -0
  28. data/lib/aasm/minitest_spec.rb +15 -0
  29. data/lib/aasm/persistence/active_record_persistence.rb +25 -101
  30. data/lib/aasm/persistence/base.rb +7 -3
  31. data/lib/aasm/persistence/mongoid_persistence.rb +25 -31
  32. data/lib/aasm/persistence/orm.rb +142 -0
  33. data/lib/aasm/persistence/redis_persistence.rb +16 -11
  34. data/lib/aasm/persistence/sequel_persistence.rb +36 -63
  35. data/lib/aasm/persistence.rb +0 -3
  36. data/lib/aasm/state_machine.rb +4 -2
  37. data/lib/aasm/state_machine_store.rb +5 -2
  38. data/lib/aasm/version.rb +1 -1
  39. data/lib/generators/active_record/templates/migration.rb +1 -1
  40. data/lib/generators/active_record/templates/migration_existing.rb +1 -1
  41. data/lib/motion-aasm.rb +2 -1
  42. data/spec/generators/active_record_generator_spec.rb +42 -39
  43. data/spec/generators/mongoid_generator_spec.rb +4 -6
  44. data/spec/models/active_record/complex_active_record_example.rb +5 -1
  45. data/spec/models/{invalid_persistor.rb → active_record/invalid_persistor.rb} +0 -2
  46. data/spec/models/{silent_persistor.rb → active_record/silent_persistor.rb} +0 -2
  47. data/spec/models/{transactor.rb → active_record/transactor.rb} +0 -2
  48. data/spec/models/{validator.rb → active_record/validator.rb} +0 -2
  49. data/spec/models/callbacks/basic.rb +5 -2
  50. data/spec/models/guard_with_params.rb +1 -1
  51. data/spec/models/guardian_without_from_specified.rb +18 -0
  52. data/spec/models/mongoid/invalid_persistor_mongoid.rb +39 -0
  53. data/spec/models/mongoid/silent_persistor_mongoid.rb +39 -0
  54. data/spec/models/mongoid/validator_mongoid.rb +100 -0
  55. data/spec/models/multiple_transitions_that_differ_only_by_guard.rb +31 -0
  56. data/spec/models/namespaced_multiple_example.rb +14 -0
  57. data/spec/models/parametrised_event.rb +7 -0
  58. data/spec/models/{mongo_mapper/complex_mongo_mapper_example.rb → redis/complex_redis_example.rb} +8 -5
  59. data/spec/models/redis/redis_multiple.rb +20 -0
  60. data/spec/models/redis/redis_simple.rb +20 -0
  61. data/spec/models/sequel/complex_sequel_example.rb +4 -3
  62. data/spec/models/sequel/invalid_persistor.rb +52 -0
  63. data/spec/models/sequel/sequel_multiple.rb +13 -13
  64. data/spec/models/sequel/sequel_simple.rb +13 -12
  65. data/spec/models/sequel/silent_persistor.rb +50 -0
  66. data/spec/models/sequel/transactor.rb +112 -0
  67. data/spec/models/sequel/validator.rb +93 -0
  68. data/spec/models/sequel/worker.rb +12 -0
  69. data/spec/models/simple_multiple_example.rb +12 -0
  70. data/spec/models/sub_class.rb +34 -0
  71. data/spec/spec_helper.rb +0 -33
  72. data/spec/spec_helpers/active_record.rb +7 -0
  73. data/spec/spec_helpers/dynamoid.rb +33 -0
  74. data/spec/spec_helpers/mongoid.rb +7 -0
  75. data/spec/spec_helpers/redis.rb +15 -0
  76. data/spec/spec_helpers/remove_warnings.rb +1 -0
  77. data/spec/spec_helpers/sequel.rb +7 -0
  78. data/spec/unit/api_spec.rb +76 -73
  79. data/spec/unit/callbacks_spec.rb +5 -0
  80. data/spec/unit/event_spec.rb +12 -0
  81. data/spec/unit/guard_spec.rb +17 -0
  82. data/spec/unit/guard_with_params_spec.rb +4 -0
  83. data/spec/unit/guard_without_from_specified_spec.rb +10 -0
  84. data/spec/unit/localizer_spec.rb +55 -53
  85. data/spec/unit/multiple_transitions_that_differ_only_by_guard_spec.rb +14 -0
  86. data/spec/unit/namespaced_multiple_example_spec.rb +22 -0
  87. data/spec/unit/override_warning_spec.rb +8 -0
  88. data/spec/unit/persistence/active_record_persistence_multiple_spec.rb +453 -449
  89. data/spec/unit/persistence/active_record_persistence_spec.rb +524 -502
  90. data/spec/unit/persistence/dynamoid_persistence_multiple_spec.rb +4 -9
  91. data/spec/unit/persistence/dynamoid_persistence_spec.rb +4 -9
  92. data/spec/unit/persistence/mongoid_persistence_multiple_spec.rb +83 -9
  93. data/spec/unit/persistence/mongoid_persistence_spec.rb +85 -9
  94. data/spec/unit/persistence/redis_persistence_multiple_spec.rb +88 -0
  95. data/spec/unit/persistence/redis_persistence_spec.rb +8 -32
  96. data/spec/unit/persistence/sequel_persistence_multiple_spec.rb +6 -11
  97. data/spec/unit/persistence/sequel_persistence_spec.rb +278 -10
  98. data/spec/unit/simple_multiple_example_spec.rb +28 -0
  99. data/spec/unit/subclassing_multiple_spec.rb +37 -2
  100. data/spec/unit/subclassing_spec.rb +17 -2
  101. data/test/minitest_helper.rb +57 -0
  102. data/test/unit/minitest_matcher_test.rb +80 -0
  103. metadata +99 -28
  104. data/gemfiles/rails_3.2_stable.gemfile +0 -15
  105. data/gemfiles/rails_4.0_mongo_mapper.gemfile +0 -16
  106. data/gemfiles/rails_4.2_mongo_mapper.gemfile +0 -17
  107. data/lib/aasm/persistence/mongo_mapper_persistence.rb +0 -163
  108. data/spec/models/mongo_mapper/no_scope_mongo_mapper.rb +0 -21
  109. data/spec/models/mongo_mapper/simple_mongo_mapper.rb +0 -23
  110. data/spec/models/mongo_mapper/simple_new_dsl_mongo_mapper.rb +0 -25
  111. data/spec/unit/persistence/mongo_mapper_persistence_multiple_spec.rb +0 -149
  112. data/spec/unit/persistence/mongo_mapper_persistence_spec.rb +0 -96
  113. /data/spec/models/{worker.rb → active_record/worker.rb} +0 -0
@@ -27,4 +27,16 @@ class SimpleMultipleExample
27
27
  transitions :from => :processing, :to => :sleeping
28
28
  end
29
29
  end
30
+
31
+ aasm(:question) do
32
+ state :answered, :initial => true
33
+ state :asked
34
+
35
+ event :ask, :binding_event => :start do
36
+ transitions :from => :answered, :to => :asked
37
+ end
38
+ event :answer, :binding_event => :stop do
39
+ transitions :from => :asked, :to => :answered
40
+ end
41
+ end
30
42
  end
@@ -1,7 +1,41 @@
1
1
  require_relative 'super_class'
2
2
 
3
3
  class SubClass < SuperClass
4
+ # Add an after callback that is not defined in the parent
5
+ aasm.state_machine.events[:foo].options[:after] = [:after_foo_event]
6
+
7
+ # Add global callback that is not defined in the parent
8
+ aasm.state_machine.global_callbacks[:after_all_transitions] = :after_all_event
9
+
10
+ attr_accessor :called_after
11
+
12
+ def after_foo_event
13
+ self.called_after = true
14
+ end
15
+
16
+ def after_all_event; end
4
17
  end
5
18
 
6
19
  class SubClassMultiple < SuperClassMultiple
20
+ # Add after callbacks that are not defined in the parent
21
+ aasm(:left).state_machine.events[:foo].options[:after] = [:left_after_foo_event]
22
+ aasm(:right).state_machine.events[:close].options[:after] = [:right_after_close_event]
23
+
24
+ # Add global callback that is not defined in the parent
25
+ aasm(:left).state_machine.global_callbacks[:after_all_transitions] = :left_after_all_event
26
+ aasm(:right).state_machine.global_callbacks[:after_all_transitions] = :right_after_all_event
27
+
28
+ attr_accessor :left_called_after, :right_called_after
29
+
30
+ def left_after_foo_event
31
+ self.left_called_after = true
32
+ end
33
+
34
+ def right_after_close_event
35
+ self.right_called_after = true
36
+ end
37
+
38
+ def left_after_all_event; end
39
+
40
+ def right_after_all_event; end
7
41
  end
data/spec/spec_helper.rb CHANGED
@@ -19,39 +19,6 @@ def load_schema
19
19
  require File.dirname(__FILE__) + "/database.rb"
20
20
  end
21
21
 
22
- # Dynamoid initialization
23
- begin
24
- require 'dynamoid'
25
- require 'aws-sdk-resources'
26
-
27
- ENV['ACCESS_KEY'] ||= 'abcd'
28
- ENV['SECRET_KEY'] ||= '1234'
29
-
30
- Aws.config.update({
31
- region: 'us-west-2',
32
- credentials: Aws::Credentials.new(ENV['ACCESS_KEY'], ENV['SECRET_KEY'])
33
- })
34
-
35
- Dynamoid.configure do |config|
36
- config.namespace = "dynamoid_tests"
37
- config.endpoint = 'http://127.0.0.1:30180'
38
- config.warn_on_scan = false
39
- end
40
-
41
- Dynamoid.logger.level = Logger::FATAL
42
-
43
- RSpec.configure do |c|
44
- c.before(:each) do
45
- Dynamoid.adapter.list_tables.each do |table|
46
- Dynamoid.adapter.delete_table(table) if table =~ /^#{Dynamoid::Config.namespace}/
47
- end
48
- Dynamoid.adapter.tables.clear
49
- end
50
- end
51
- rescue LoadError
52
- # Without Dynamoid settings
53
- end
54
-
55
22
  # custom spec helpers
56
23
  Dir[File.dirname(__FILE__) + "/spec_helpers/**/*.rb"].sort.each { |f| require File.expand_path(f) }
57
24
 
@@ -0,0 +1,7 @@
1
+ # encoding: utf-8
2
+ begin
3
+ require 'active_record'
4
+ puts "active_record gem found, running ActiveRecord specs \e[32m#{'✔'}\e[0m"
5
+ rescue LoadError
6
+ puts "active_record gem not found, not running ActiveRecord specs \e[31m#{'✖'}\e[0m"
7
+ end
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+ begin
3
+ require 'dynamoid'
4
+ require 'aws-sdk-resources'
5
+ puts "dynamoid gem found, running Dynamoid specs \e[32m#{'✔'}\e[0m"
6
+
7
+ ENV['ACCESS_KEY'] ||= 'abcd'
8
+ ENV['SECRET_KEY'] ||= '1234'
9
+
10
+ Aws.config.update({
11
+ region: 'us-west-2',
12
+ credentials: Aws::Credentials.new(ENV['ACCESS_KEY'], ENV['SECRET_KEY'])
13
+ })
14
+
15
+ Dynamoid.configure do |config|
16
+ config.namespace = "dynamoid_tests"
17
+ config.endpoint = 'http://127.0.0.1:30180'
18
+ config.warn_on_scan = false
19
+ end
20
+
21
+ Dynamoid.logger.level = Logger::FATAL
22
+
23
+ RSpec.configure do |c|
24
+ c.before(:each) do
25
+ Dynamoid.adapter.list_tables.each do |table|
26
+ Dynamoid.adapter.delete_table(table) if table =~ /^#{Dynamoid::Config.namespace}/
27
+ end
28
+ Dynamoid.adapter.tables.clear
29
+ end
30
+ end
31
+ rescue LoadError
32
+ puts "dynamoid gem not found, not running Dynamoid specs \e[31m#{'✖'}\e[0m"
33
+ end
@@ -0,0 +1,7 @@
1
+ # encoding: utf-8
2
+ begin
3
+ require 'mongoid'
4
+ puts "mongoid gem found, running mongoid specs \e[32m#{'✔'}\e[0m"
5
+ rescue LoadError
6
+ puts "mongoid gem not found, not running mongoid specs \e[31m#{'✖'}\e[0m"
7
+ end
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+ begin
3
+ require 'redis-objects'
4
+ puts "redis-objects gem found, running Redis specs \e[32m#{'✔'}\e[0m"
5
+
6
+ Redis.current = Redis.new(host: '127.0.0.1', port: 6379)
7
+
8
+ RSpec.configure do |c|
9
+ c.before(:each) do
10
+ Redis.current.keys('redis_*').each { |k| Redis.current.del k }
11
+ end
12
+ end
13
+ rescue LoadError
14
+ puts "redis-objects gem not found, not running Redis specs \e[31m#{'✖'}\e[0m"
15
+ end
@@ -0,0 +1 @@
1
+ AASM::Configuration.hide_warnings = true
@@ -0,0 +1,7 @@
1
+ # encoding: utf-8
2
+ begin
3
+ require 'sequel'
4
+ puts "sequel gem found, running Sequel specs \e[32m#{'✔'}\e[0m"
5
+ rescue LoadError
6
+ puts "sequel gem not found, not running Sequel specs \e[31m#{'✖'}\e[0m"
7
+ end
@@ -1,97 +1,100 @@
1
1
  require 'spec_helper'
2
- require 'models/default_state.rb'
3
- require 'models/provided_state.rb'
4
- require 'models/active_record/persisted_state.rb'
5
- require 'models/active_record/provided_and_persisted_state.rb'
6
2
 
7
- load_schema
3
+ if defined?(ActiveRecord)
4
+ require 'models/default_state.rb'
5
+ require 'models/provided_state.rb'
6
+ require 'models/active_record/persisted_state.rb'
7
+ require 'models/active_record/provided_and_persisted_state.rb'
8
8
 
9
- describe "reading the current state" do
10
- it "uses the AASM default" do
11
- expect(DefaultState.new.aasm.current_state).to eql :alpha
12
- end
13
-
14
- it "uses the provided method" do
15
- expect(ProvidedState.new.aasm.current_state).to eql :beta
16
- end
9
+ load_schema
17
10
 
18
- it "uses the persistence storage" do
19
- expect(PersistedState.new.aasm.current_state).to eql :alpha
20
- end
11
+ describe "reading the current state" do
12
+ it "uses the AASM default" do
13
+ expect(DefaultState.new.aasm.current_state).to eql :alpha
14
+ end
21
15
 
22
- it "uses the provided method even if persisted" do
23
- expect(ProvidedAndPersistedState.new.aasm.current_state).to eql :gamma
24
- end
16
+ it "uses the provided method" do
17
+ expect(ProvidedState.new.aasm.current_state).to eql :beta
18
+ end
25
19
 
26
- context "after dup" do
27
20
  it "uses the persistence storage" do
28
- source = PersistedState.create!
29
- copy = source.dup
30
- copy.save!
21
+ expect(PersistedState.new.aasm.current_state).to eql :alpha
22
+ end
31
23
 
32
- copy.release!
24
+ it "uses the provided method even if persisted" do
25
+ expect(ProvidedAndPersistedState.new.aasm.current_state).to eql :gamma
26
+ end
27
+
28
+ context "after dup" do
29
+ it "uses the persistence storage" do
30
+ source = PersistedState.create!
31
+ copy = source.dup
32
+ copy.save!
33
33
 
34
- expect(source.aasm_state).to eql 'alpha'
35
- expect(source.aasm.current_state).to eql :alpha
34
+ copy.release!
36
35
 
37
- source2 = PersistedState.find(source.id)
38
- expect(source2.reload.aasm_state).to eql 'alpha'
39
- expect(source2.aasm.current_state).to eql :alpha
36
+ expect(source.aasm_state).to eql 'alpha'
37
+ expect(source.aasm.current_state).to eql :alpha
40
38
 
41
- expect(copy.aasm_state).to eql 'beta'
42
- expect(copy.aasm.current_state).to eql :beta
39
+ source2 = PersistedState.find(source.id)
40
+ expect(source2.reload.aasm_state).to eql 'alpha'
41
+ expect(source2.aasm.current_state).to eql :alpha
42
+
43
+ expect(copy.aasm_state).to eql 'beta'
44
+ expect(copy.aasm.current_state).to eql :beta
45
+ end
43
46
  end
44
47
  end
45
- end
46
48
 
47
- describe "writing and persisting the current state" do
48
- it "uses the AASM default" do
49
- o = DefaultState.new
50
- o.release!
51
- expect(o.persisted_store).to be_nil
52
- end
49
+ describe "writing and persisting the current state" do
50
+ it "uses the AASM default" do
51
+ o = DefaultState.new
52
+ o.release!
53
+ expect(o.persisted_store).to be_nil
54
+ end
53
55
 
54
- it "uses the provided method" do
55
- o = ProvidedState.new
56
- o.release!
57
- expect(o.persisted_store).to eql :beta
58
- end
56
+ it "uses the provided method" do
57
+ o = ProvidedState.new
58
+ o.release!
59
+ expect(o.persisted_store).to eql :beta
60
+ end
59
61
 
60
- it "uses the persistence storage" do
61
- o = PersistedState.new
62
- o.release!
63
- expect(o.persisted_store).to be_nil
64
- end
62
+ it "uses the persistence storage" do
63
+ o = PersistedState.new
64
+ o.release!
65
+ expect(o.persisted_store).to be_nil
66
+ end
65
67
 
66
- it "uses the provided method even if persisted" do
67
- o = ProvidedAndPersistedState.new
68
- o.release!
69
- expect(o.persisted_store).to eql :beta
68
+ it "uses the provided method even if persisted" do
69
+ o = ProvidedAndPersistedState.new
70
+ o.release!
71
+ expect(o.persisted_store).to eql :beta
72
+ end
70
73
  end
71
- end
72
74
 
73
- describe "writing the current state without persisting it" do
74
- it "uses the AASM default" do
75
- o = DefaultState.new
76
- o.release
77
- expect(o.transient_store).to be_nil
78
- end
75
+ describe "writing the current state without persisting it" do
76
+ it "uses the AASM default" do
77
+ o = DefaultState.new
78
+ o.release
79
+ expect(o.transient_store).to be_nil
80
+ end
79
81
 
80
- it "uses the provided method" do
81
- o = ProvidedState.new
82
- o.release
83
- expect(o.transient_store).to eql :beta
84
- end
82
+ it "uses the provided method" do
83
+ o = ProvidedState.new
84
+ o.release
85
+ expect(o.transient_store).to eql :beta
86
+ end
85
87
 
86
- it "uses the persistence storage" do
87
- o = PersistedState.new
88
- o.release
89
- expect(o.transient_store).to be_nil
90
- end
88
+ it "uses the persistence storage" do
89
+ o = PersistedState.new
90
+ o.release
91
+ expect(o.transient_store).to be_nil
92
+ end
91
93
 
92
- it "uses the provided method even if persisted" do
93
- o = ProvidedAndPersistedState.new
94
- o.release
95
- expect(o.transient_store).to eql :beta
94
+ it "uses the provided method even if persisted" do
95
+ o = ProvidedAndPersistedState.new
96
+ o.release
97
+ expect(o.transient_store).to eql :beta
98
+ end
96
99
  end
97
100
  end
@@ -118,6 +118,7 @@ describe 'callbacks for the new DSL' do
118
118
  expect(callback).to receive(:before_enter_closed).once.ordered
119
119
  expect(callback).to receive(:enter_closed).once.ordered
120
120
  expect(callback).to receive(:aasm_write_state).once.ordered.and_return(true) # this is when the state changes
121
+ expect(callback).to receive(:event_before_success).once.ordered
121
122
  expect(callback).to receive(:success_transition).once.ordered.and_return(true) # these should be after the state changes
122
123
  expect(callback).to receive(:after_exit_open).once.ordered
123
124
  expect(callback).to receive(:after_enter_closed).once.ordered
@@ -143,6 +144,7 @@ describe 'callbacks for the new DSL' do
143
144
  expect(callback).to_not receive(:before_enter_closed)
144
145
  expect(callback).to_not receive(:enter_closed)
145
146
  expect(callback).to_not receive(:aasm_write_state)
147
+ expect(callback).to_not receive(:event_before_success)
146
148
  expect(callback).to_not receive(:success_transition)
147
149
  expect(callback).to_not receive(:after_exit_open)
148
150
  expect(callback).to_not receive(:after_enter_closed)
@@ -186,6 +188,7 @@ describe 'callbacks for the new DSL' do
186
188
  expect(callback).to_not receive(:before_enter_closed)
187
189
  expect(callback).to_not receive(:enter_closed)
188
190
  expect(callback).to_not receive(:aasm_write_state)
191
+ expect(callback).to_not receive(:event_before_success)
189
192
  expect(callback).to_not receive(:success_transition)
190
193
  expect(callback).to_not receive(:after_exit_open)
191
194
  expect(callback).to_not receive(:after_enter_closed)
@@ -217,6 +220,7 @@ describe 'callbacks for the new DSL' do
217
220
  expect(callback).to receive(:after).once.ordered
218
221
 
219
222
  expect(callback).to_not receive(:transitioning)
223
+ expect(callback).to_not receive(:event_before_success)
220
224
  expect(callback).to_not receive(:success_transition)
221
225
  expect(callback).to_not receive(:before_enter_closed)
222
226
  expect(callback).to_not receive(:enter_closed)
@@ -240,6 +244,7 @@ describe 'callbacks for the new DSL' do
240
244
  expect(callback).to_not receive(:before_enter_closed)
241
245
  expect(callback).to_not receive(:enter_closed)
242
246
  expect(callback).to_not receive(:aasm_write_state)
247
+ expect(callback).to_not receive(:event_before_success)
243
248
  expect(callback).to_not receive(:success_transition)
244
249
  expect(callback).to_not receive(:after_exit_open)
245
250
  expect(callback).to_not receive(:after_enter_closed)
@@ -325,6 +325,12 @@ describe 'parametrised events' do
325
325
  pe.dress!(:working, 'blue', 'jeans')
326
326
  end
327
327
 
328
+ it 'should call :after transition method if arg is nil' do
329
+ dryer = nil
330
+ expect(pe).to receive(:wet_hair).with(dryer)
331
+ pe.shower!(dryer)
332
+ end
333
+
328
334
  it 'should call :after transition proc' do
329
335
  pe.wakeup!(:showering)
330
336
  expect(pe).to receive(:wear_clothes).with('purple', 'slacks')
@@ -344,6 +350,12 @@ describe 'parametrised events' do
344
350
  pe.dress!(:working, 'foundation', 'SPF')
345
351
  end
346
352
 
353
+ it 'should call :success transition method if arg is nil' do
354
+ shirt_color = nil
355
+ expect(pe).to receive(:wear_clothes).with(shirt_color)
356
+ pe.shower!(shirt_color)
357
+ end
358
+
347
359
  it 'should call :success transition proc' do
348
360
  pe.wakeup!(:showering)
349
361
  expect(pe).to receive(:wear_makeup).with('purple', 'slacks')
@@ -70,3 +70,20 @@ describe "event guards" do
70
70
  end
71
71
 
72
72
  end
73
+
74
+ if defined?(ActiveRecord)
75
+
76
+ Dir[File.dirname(__FILE__) + "/../models/active_record/*.rb"].sort.each do |f|
77
+ require File.expand_path(f)
78
+ end
79
+
80
+ load_schema
81
+
82
+ describe "ActiveRecord per-transition guards" do
83
+ let(:example) { ComplexActiveRecordExample.new }
84
+
85
+ it "should be able to increment" do
86
+ expect(example.may_increment?).to be true
87
+ end
88
+ end
89
+ end
@@ -7,4 +7,8 @@ describe "guards with params" do
7
7
  it "list permitted states" do
8
8
  expect(guard.aasm.states({:permitted => true}, user).map(&:name)).to eql [:reviewed]
9
9
  end
10
+
11
+ it "list no states if user is blank" do
12
+ expect(guard.aasm.states({:permitted => true}, nil).map(&:name)).to eql []
13
+ end
10
14
  end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe "transitions without from specified" do
4
+ let(:guardian) { GuardianWithoutFromSpecified.new }
5
+
6
+ it "allows the transitions if guard succeeds" do
7
+ expect { guardian.use_guards_where_the_first_fails! }.to_not raise_error
8
+ expect(guardian).to be_gamma
9
+ end
10
+ end
@@ -1,76 +1,78 @@
1
1
  require 'spec_helper'
2
- require 'active_record'
3
- require 'i18n'
4
2
 
5
- I18n.enforce_available_locales = false
6
- load_schema
3
+ if defined?(ActiceRecord)
4
+ require 'i18n'
7
5
 
8
- describe AASM::Localizer, "new style" do
9
- before(:all) do
10
- I18n.load_path << 'spec/en.yml'
11
- I18n.default_locale = :en
12
- I18n.reload!
13
- end
14
-
15
- after(:all) do
16
- I18n.load_path.clear
17
- end
18
-
19
- let (:foo_opened) { LocalizerTestModel.new }
20
- let (:foo_closed) { LocalizerTestModel.new.tap { |x| x.aasm_state = :closed } }
6
+ I18n.enforce_available_locales = false
7
+ load_schema
21
8
 
22
- context 'aasm.human_state' do
23
- it 'should return translated state value' do
24
- expect(foo_opened.aasm.human_state).to eq("It's open now!")
9
+ describe AASM::Localizer, "new style" do
10
+ before(:all) do
11
+ I18n.load_path << 'spec/en.yml'
12
+ I18n.default_locale = :en
13
+ I18n.reload!
25
14
  end
26
15
 
27
- it 'should return humanized value if not localized' do
28
- expect(foo_closed.aasm.human_state).to eq("Closed")
16
+ after(:all) do
17
+ I18n.load_path.clear
29
18
  end
30
- end
31
19
 
32
- context 'aasm.human_event_name' do
33
- it 'should return translated event name' do
34
- expect(LocalizerTestModel.aasm.human_event_name(:close)).to eq("Let's close it!")
35
- end
20
+ let (:foo_opened) { LocalizerTestModel.new }
21
+ let (:foo_closed) { LocalizerTestModel.new.tap { |x| x.aasm_state = :closed } }
36
22
 
37
- it 'should return humanized event name' do
38
- expect(LocalizerTestModel.aasm.human_event_name(:open)).to eq("Open")
23
+ context 'aasm.human_state' do
24
+ it 'should return translated state value' do
25
+ expect(foo_opened.aasm.human_state).to eq("It's open now!")
26
+ end
27
+
28
+ it 'should return humanized value if not localized' do
29
+ expect(foo_closed.aasm.human_state).to eq("Closed")
30
+ end
39
31
  end
40
- end
41
- end
42
32
 
43
- describe AASM::Localizer, "deprecated style" do
44
- before(:all) do
45
- I18n.load_path << 'spec/en_deprecated_style.yml'
46
- I18n.default_locale = :en
47
- I18n.reload!
48
- end
33
+ context 'aasm.human_event_name' do
34
+ it 'should return translated event name' do
35
+ expect(LocalizerTestModel.aasm.human_event_name(:close)).to eq("Let's close it!")
36
+ end
49
37
 
50
- after(:all) do
51
- I18n.load_path.clear
38
+ it 'should return humanized event name' do
39
+ expect(LocalizerTestModel.aasm.human_event_name(:open)).to eq("Open")
40
+ end
41
+ end
52
42
  end
53
43
 
54
- let (:foo_opened) { LocalizerTestModel.new }
55
- let (:foo_closed) { LocalizerTestModel.new.tap { |x| x.aasm_state = :closed } }
56
-
57
- context 'aasm.human_state' do
58
- it 'should return translated state value' do
59
- expect(foo_opened.aasm.human_state).to eq("It's open now!")
44
+ describe AASM::Localizer, "deprecated style" do
45
+ before(:all) do
46
+ I18n.load_path << 'spec/en_deprecated_style.yml'
47
+ I18n.default_locale = :en
48
+ I18n.reload!
60
49
  end
61
50
 
62
- it 'should return humanized value if not localized' do
63
- expect(foo_closed.aasm.human_state).to eq("Closed")
51
+ after(:all) do
52
+ I18n.load_path.clear
64
53
  end
65
- end
66
54
 
67
- context 'aasm.human_event_name' do
68
- it 'should return translated event name' do
69
- expect(LocalizerTestModel.aasm.human_event_name(:close)).to eq("Let's close it!")
55
+ let (:foo_opened) { LocalizerTestModel.new }
56
+ let (:foo_closed) { LocalizerTestModel.new.tap { |x| x.aasm_state = :closed } }
57
+
58
+ context 'aasm.human_state' do
59
+ it 'should return translated state value' do
60
+ expect(foo_opened.aasm.human_state).to eq("It's open now!")
61
+ end
62
+
63
+ it 'should return humanized value if not localized' do
64
+ expect(foo_closed.aasm.human_state).to eq("Closed")
65
+ end
70
66
  end
71
67
 
72
- it 'should return humanized event name' do
73
- expect(LocalizerTestModel.aasm.human_event_name(:open)).to eq("Open")
68
+ context 'aasm.human_event_name' do
69
+ it 'should return translated event name' do
70
+ expect(LocalizerTestModel.aasm.human_event_name(:close)).to eq("Let's close it!")
71
+ end
72
+
73
+ it 'should return humanized event name' do
74
+ expect(LocalizerTestModel.aasm.human_event_name(:open)).to eq("Open")
75
+ end
74
76
  end
75
77
  end
76
78
  end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ describe "multiple transitions that differ only by guard" do
4
+ let(:job) { MultipleTransitionsThatDifferOnlyByGuard.new }
5
+
6
+ it 'does not follow the first transition if its guard fails' do
7
+ expect{job.go}.not_to raise_error
8
+ end
9
+
10
+ it 'executes the second transition\'s callbacks' do
11
+ job.go
12
+ expect(job.executed_second).to be_truthy
13
+ end
14
+ end
@@ -11,6 +11,10 @@ describe 'state machine' do
11
11
  expect(namespaced.aasm(:review_status).current_state).to eq(:unapproved)
12
12
  expect(namespaced).to respond_to(:review_unapproved?)
13
13
  expect(namespaced).to be_review_unapproved
14
+
15
+ expect(namespaced.aasm(:car).current_state).to eq(:unsold)
16
+ expect(namespaced).to respond_to(:car_unsold?)
17
+ expect(namespaced).to be_car_unsold
14
18
  end
15
19
 
16
20
  it 'allows transitions to other states' do
@@ -25,6 +29,12 @@ describe 'state machine' do
25
29
  namespaced.approve_review!
26
30
  expect(namespaced).to respond_to(:review_approved?)
27
31
  expect(namespaced).to be_review_approved
32
+
33
+ expect(namespaced).to respond_to(:sell_car)
34
+ expect(namespaced).to respond_to(:sell_car!)
35
+ namespaced.sell_car!
36
+ expect(namespaced).to respond_to(:car_sold?)
37
+ expect(namespaced).to be_car_sold
28
38
  end
29
39
 
30
40
  it 'denies transitions to other states' do
@@ -41,6 +51,13 @@ describe 'state machine' do
41
51
  expect {namespaced.approve_review}.to raise_error(AASM::InvalidTransition)
42
52
  expect {namespaced.approve_review!}.to raise_error(AASM::InvalidTransition)
43
53
  namespaced.unapprove_review
54
+
55
+ expect {namespaced.return_car}.to raise_error(AASM::InvalidTransition)
56
+ expect {namespaced.return_car!}.to raise_error(AASM::InvalidTransition)
57
+ namespaced.sell_car
58
+ expect {namespaced.sell_car}.to raise_error(AASM::InvalidTransition)
59
+ expect {namespaced.sell_car!}.to raise_error(AASM::InvalidTransition)
60
+ namespaced.return_car
44
61
  end
45
62
 
46
63
  it 'defines constants for each state name' do
@@ -49,5 +66,10 @@ describe 'state machine' do
49
66
 
50
67
  expect(NamespacedMultipleExample::STATE_REVIEW_UNAPPROVED).to eq(:unapproved)
51
68
  expect(NamespacedMultipleExample::STATE_REVIEW_APPROVED).to eq(:approved)
69
+
70
+ expect(NamespacedMultipleExample::STATE_CAR_UNSOLD).to eq(:unsold)
71
+ expect(NamespacedMultipleExample::STATE_CAR_SOLD).to eq(:sold)
52
72
  end
73
+
74
+
53
75
  end