aasm 5.0.8

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 (262) hide show
  1. checksums.yaml +7 -0
  2. data/.document +6 -0
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +27 -0
  4. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  5. data/.gitignore +20 -0
  6. data/.travis.yml +100 -0
  7. data/API +34 -0
  8. data/Appraisals +71 -0
  9. data/CHANGELOG.md +431 -0
  10. data/CODE_OF_CONDUCT.md +13 -0
  11. data/CONTRIBUTING.md +24 -0
  12. data/Dockerfile +44 -0
  13. data/Gemfile +6 -0
  14. data/Gemfile.lock_old +151 -0
  15. data/HOWTO +12 -0
  16. data/LICENSE +20 -0
  17. data/PLANNED_CHANGES.md +11 -0
  18. data/README.md +1439 -0
  19. data/README_FROM_VERSION_3_TO_4.md +240 -0
  20. data/Rakefile +31 -0
  21. data/TESTING.md +25 -0
  22. data/aasm.gemspec +37 -0
  23. data/callbacks.txt +51 -0
  24. data/docker-compose.yml +40 -0
  25. data/gemfiles/norails.gemfile +10 -0
  26. data/gemfiles/rails_3.2.gemfile +14 -0
  27. data/gemfiles/rails_4.2.gemfile +16 -0
  28. data/gemfiles/rails_4.2_mongoid_5.gemfile +11 -0
  29. data/gemfiles/rails_4.2_nobrainer.gemfile +9 -0
  30. data/gemfiles/rails_5.0.gemfile +13 -0
  31. data/gemfiles/rails_5.0_nobrainer.gemfile +9 -0
  32. data/gemfiles/rails_5.1.gemfile +13 -0
  33. data/gemfiles/rails_5.2.gemfile +13 -0
  34. data/lib/aasm.rb +23 -0
  35. data/lib/aasm/aasm.rb +208 -0
  36. data/lib/aasm/base.rb +271 -0
  37. data/lib/aasm/configuration.rb +45 -0
  38. data/lib/aasm/core/event.rb +172 -0
  39. data/lib/aasm/core/invoker.rb +129 -0
  40. data/lib/aasm/core/invokers/base_invoker.rb +75 -0
  41. data/lib/aasm/core/invokers/class_invoker.rb +52 -0
  42. data/lib/aasm/core/invokers/literal_invoker.rb +47 -0
  43. data/lib/aasm/core/invokers/proc_invoker.rb +59 -0
  44. data/lib/aasm/core/state.rb +90 -0
  45. data/lib/aasm/core/transition.rb +83 -0
  46. data/lib/aasm/dsl_helper.rb +30 -0
  47. data/lib/aasm/errors.rb +21 -0
  48. data/lib/aasm/instance_base.rb +133 -0
  49. data/lib/aasm/localizer.rb +54 -0
  50. data/lib/aasm/minitest.rb +5 -0
  51. data/lib/aasm/minitest/allow_event.rb +13 -0
  52. data/lib/aasm/minitest/allow_transition_to.rb +13 -0
  53. data/lib/aasm/minitest/have_state.rb +13 -0
  54. data/lib/aasm/minitest/transition_from.rb +21 -0
  55. data/lib/aasm/minitest_spec.rb +15 -0
  56. data/lib/aasm/persistence.rb +54 -0
  57. data/lib/aasm/persistence/active_record_persistence.rb +165 -0
  58. data/lib/aasm/persistence/base.rb +78 -0
  59. data/lib/aasm/persistence/core_data_query_persistence.rb +94 -0
  60. data/lib/aasm/persistence/dynamoid_persistence.rb +92 -0
  61. data/lib/aasm/persistence/mongoid_persistence.rb +126 -0
  62. data/lib/aasm/persistence/no_brainer_persistence.rb +105 -0
  63. data/lib/aasm/persistence/orm.rb +150 -0
  64. data/lib/aasm/persistence/plain_persistence.rb +26 -0
  65. data/lib/aasm/persistence/redis_persistence.rb +112 -0
  66. data/lib/aasm/persistence/sequel_persistence.rb +83 -0
  67. data/lib/aasm/rspec.rb +5 -0
  68. data/lib/aasm/rspec/allow_event.rb +26 -0
  69. data/lib/aasm/rspec/allow_transition_to.rb +26 -0
  70. data/lib/aasm/rspec/have_state.rb +22 -0
  71. data/lib/aasm/rspec/transition_from.rb +36 -0
  72. data/lib/aasm/state_machine.rb +53 -0
  73. data/lib/aasm/state_machine_store.rb +76 -0
  74. data/lib/aasm/version.rb +3 -0
  75. data/lib/generators/aasm/aasm_generator.rb +16 -0
  76. data/lib/generators/aasm/orm_helpers.rb +41 -0
  77. data/lib/generators/active_record/aasm_generator.rb +40 -0
  78. data/lib/generators/active_record/templates/migration.rb +8 -0
  79. data/lib/generators/active_record/templates/migration_existing.rb +5 -0
  80. data/lib/generators/mongoid/aasm_generator.rb +28 -0
  81. data/lib/generators/nobrainer/aasm_generator.rb +28 -0
  82. data/lib/motion-aasm.rb +37 -0
  83. data/spec/database.rb +59 -0
  84. data/spec/database.yml +3 -0
  85. data/spec/en.yml +12 -0
  86. data/spec/en_deprecated_style.yml +10 -0
  87. data/spec/generators/active_record_generator_spec.rb +53 -0
  88. data/spec/generators/mongoid_generator_spec.rb +31 -0
  89. data/spec/generators/no_brainer_generator_spec.rb +29 -0
  90. data/spec/models/active_record/basic_active_record_two_state_machines_example.rb +25 -0
  91. data/spec/models/active_record/complex_active_record_example.rb +37 -0
  92. data/spec/models/active_record/derivate_new_dsl.rb +7 -0
  93. data/spec/models/active_record/false_state.rb +35 -0
  94. data/spec/models/active_record/gate.rb +39 -0
  95. data/spec/models/active_record/instance_level_skip_validation_example.rb +19 -0
  96. data/spec/models/active_record/invalid_persistor.rb +29 -0
  97. data/spec/models/active_record/localizer_test_model.rb +34 -0
  98. data/spec/models/active_record/no_direct_assignment.rb +21 -0
  99. data/spec/models/active_record/no_scope.rb +21 -0
  100. data/spec/models/active_record/persisted_state.rb +12 -0
  101. data/spec/models/active_record/person.rb +23 -0
  102. data/spec/models/active_record/provided_and_persisted_state.rb +24 -0
  103. data/spec/models/active_record/reader.rb +7 -0
  104. data/spec/models/active_record/readme_job.rb +21 -0
  105. data/spec/models/active_record/silent_persistor.rb +29 -0
  106. data/spec/models/active_record/simple_new_dsl.rb +32 -0
  107. data/spec/models/active_record/thief.rb +29 -0
  108. data/spec/models/active_record/transactor.rb +124 -0
  109. data/spec/models/active_record/transient.rb +6 -0
  110. data/spec/models/active_record/validator.rb +118 -0
  111. data/spec/models/active_record/with_enum.rb +39 -0
  112. data/spec/models/active_record/with_enum_without_column.rb +38 -0
  113. data/spec/models/active_record/with_false_enum.rb +31 -0
  114. data/spec/models/active_record/with_true_enum.rb +39 -0
  115. data/spec/models/active_record/work.rb +3 -0
  116. data/spec/models/active_record/worker.rb +2 -0
  117. data/spec/models/active_record/writer.rb +6 -0
  118. data/spec/models/basic_two_state_machines_example.rb +25 -0
  119. data/spec/models/callbacks/basic.rb +98 -0
  120. data/spec/models/callbacks/basic_multiple.rb +75 -0
  121. data/spec/models/callbacks/guard_within_block.rb +67 -0
  122. data/spec/models/callbacks/guard_within_block_multiple.rb +66 -0
  123. data/spec/models/callbacks/multiple_transitions_transition_guard.rb +66 -0
  124. data/spec/models/callbacks/multiple_transitions_transition_guard_multiple.rb +65 -0
  125. data/spec/models/callbacks/private_method.rb +44 -0
  126. data/spec/models/callbacks/private_method_multiple.rb +44 -0
  127. data/spec/models/callbacks/with_args.rb +62 -0
  128. data/spec/models/callbacks/with_args_multiple.rb +61 -0
  129. data/spec/models/callbacks/with_state_arg.rb +34 -0
  130. data/spec/models/callbacks/with_state_arg_multiple.rb +29 -0
  131. data/spec/models/complex_example.rb +222 -0
  132. data/spec/models/conversation.rb +93 -0
  133. data/spec/models/default_state.rb +12 -0
  134. data/spec/models/double_definer.rb +21 -0
  135. data/spec/models/dynamoid/complex_dynamoid_example.rb +37 -0
  136. data/spec/models/dynamoid/dynamoid_multiple.rb +18 -0
  137. data/spec/models/dynamoid/dynamoid_simple.rb +18 -0
  138. data/spec/models/foo.rb +106 -0
  139. data/spec/models/foo_callback_multiple.rb +45 -0
  140. data/spec/models/guard_arguments_check.rb +17 -0
  141. data/spec/models/guard_with_params.rb +24 -0
  142. data/spec/models/guard_with_params_multiple.rb +18 -0
  143. data/spec/models/guardian.rb +58 -0
  144. data/spec/models/guardian_multiple.rb +48 -0
  145. data/spec/models/guardian_without_from_specified.rb +18 -0
  146. data/spec/models/initial_state_proc.rb +31 -0
  147. data/spec/models/mongoid/complex_mongoid_example.rb +37 -0
  148. data/spec/models/mongoid/invalid_persistor_mongoid.rb +39 -0
  149. data/spec/models/mongoid/mongoid_relationships.rb +26 -0
  150. data/spec/models/mongoid/no_scope_mongoid.rb +21 -0
  151. data/spec/models/mongoid/silent_persistor_mongoid.rb +39 -0
  152. data/spec/models/mongoid/simple_mongoid.rb +23 -0
  153. data/spec/models/mongoid/simple_new_dsl_mongoid.rb +25 -0
  154. data/spec/models/mongoid/validator_mongoid.rb +100 -0
  155. data/spec/models/multi_transitioner.rb +34 -0
  156. data/spec/models/multiple_transitions_that_differ_only_by_guard.rb +31 -0
  157. data/spec/models/namespaced_multiple_example.rb +42 -0
  158. data/spec/models/no_initial_state.rb +25 -0
  159. data/spec/models/nobrainer/complex_no_brainer_example.rb +36 -0
  160. data/spec/models/nobrainer/invalid_persistor_no_brainer.rb +39 -0
  161. data/spec/models/nobrainer/no_scope_no_brainer.rb +21 -0
  162. data/spec/models/nobrainer/nobrainer_relationships.rb +25 -0
  163. data/spec/models/nobrainer/silent_persistor_no_brainer.rb +39 -0
  164. data/spec/models/nobrainer/simple_new_dsl_nobrainer.rb +25 -0
  165. data/spec/models/nobrainer/simple_no_brainer.rb +23 -0
  166. data/spec/models/nobrainer/validator_no_brainer.rb +98 -0
  167. data/spec/models/not_auto_loaded/process.rb +21 -0
  168. data/spec/models/parametrised_event.rb +42 -0
  169. data/spec/models/parametrised_event_multiple.rb +29 -0
  170. data/spec/models/process_with_new_dsl.rb +31 -0
  171. data/spec/models/provided_state.rb +24 -0
  172. data/spec/models/redis/complex_redis_example.rb +40 -0
  173. data/spec/models/redis/redis_multiple.rb +20 -0
  174. data/spec/models/redis/redis_simple.rb +20 -0
  175. data/spec/models/sequel/complex_sequel_example.rb +46 -0
  176. data/spec/models/sequel/invalid_persistor.rb +52 -0
  177. data/spec/models/sequel/sequel_multiple.rb +25 -0
  178. data/spec/models/sequel/sequel_simple.rb +26 -0
  179. data/spec/models/sequel/silent_persistor.rb +50 -0
  180. data/spec/models/sequel/transactor.rb +112 -0
  181. data/spec/models/sequel/validator.rb +93 -0
  182. data/spec/models/sequel/worker.rb +12 -0
  183. data/spec/models/silencer.rb +27 -0
  184. data/spec/models/simple_custom_example.rb +53 -0
  185. data/spec/models/simple_example.rb +23 -0
  186. data/spec/models/simple_example_with_guard_args.rb +17 -0
  187. data/spec/models/simple_multiple_example.rb +42 -0
  188. data/spec/models/state_machine_with_failed_event.rb +20 -0
  189. data/spec/models/states_on_one_line_example.rb +8 -0
  190. data/spec/models/sub_class.rb +41 -0
  191. data/spec/models/sub_class_with_more_states.rb +18 -0
  192. data/spec/models/sub_classing.rb +3 -0
  193. data/spec/models/super_class.rb +46 -0
  194. data/spec/models/this_name_better_not_be_in_use.rb +11 -0
  195. data/spec/models/valid_state_name.rb +23 -0
  196. data/spec/spec_helper.rb +36 -0
  197. data/spec/spec_helpers/active_record.rb +8 -0
  198. data/spec/spec_helpers/dynamoid.rb +35 -0
  199. data/spec/spec_helpers/mongoid.rb +26 -0
  200. data/spec/spec_helpers/nobrainer.rb +15 -0
  201. data/spec/spec_helpers/redis.rb +18 -0
  202. data/spec/spec_helpers/remove_warnings.rb +1 -0
  203. data/spec/spec_helpers/sequel.rb +7 -0
  204. data/spec/unit/abstract_class_spec.rb +27 -0
  205. data/spec/unit/api_spec.rb +100 -0
  206. data/spec/unit/basic_two_state_machines_example_spec.rb +10 -0
  207. data/spec/unit/callback_multiple_spec.rb +304 -0
  208. data/spec/unit/callbacks_spec.rb +521 -0
  209. data/spec/unit/complex_example_spec.rb +93 -0
  210. data/spec/unit/complex_multiple_example_spec.rb +115 -0
  211. data/spec/unit/edge_cases_spec.rb +16 -0
  212. data/spec/unit/event_multiple_spec.rb +73 -0
  213. data/spec/unit/event_naming_spec.rb +16 -0
  214. data/spec/unit/event_spec.rb +394 -0
  215. data/spec/unit/exception_spec.rb +11 -0
  216. data/spec/unit/guard_arguments_check_spec.rb +9 -0
  217. data/spec/unit/guard_multiple_spec.rb +60 -0
  218. data/spec/unit/guard_spec.rb +89 -0
  219. data/spec/unit/guard_with_params_multiple_spec.rb +10 -0
  220. data/spec/unit/guard_with_params_spec.rb +14 -0
  221. data/spec/unit/guard_without_from_specified_spec.rb +10 -0
  222. data/spec/unit/initial_state_multiple_spec.rb +15 -0
  223. data/spec/unit/initial_state_spec.rb +12 -0
  224. data/spec/unit/inspection_multiple_spec.rb +201 -0
  225. data/spec/unit/inspection_spec.rb +149 -0
  226. data/spec/unit/invoker_spec.rb +189 -0
  227. data/spec/unit/invokers/base_invoker_spec.rb +72 -0
  228. data/spec/unit/invokers/class_invoker_spec.rb +95 -0
  229. data/spec/unit/invokers/literal_invoker_spec.rb +86 -0
  230. data/spec/unit/invokers/proc_invoker_spec.rb +86 -0
  231. data/spec/unit/localizer_spec.rb +78 -0
  232. data/spec/unit/memory_leak_spec.rb +38 -0
  233. data/spec/unit/multiple_transitions_that_differ_only_by_guard_spec.rb +14 -0
  234. data/spec/unit/namespaced_multiple_example_spec.rb +75 -0
  235. data/spec/unit/new_dsl_spec.rb +12 -0
  236. data/spec/unit/override_warning_spec.rb +94 -0
  237. data/spec/unit/persistence/active_record_persistence_multiple_spec.rb +618 -0
  238. data/spec/unit/persistence/active_record_persistence_spec.rb +773 -0
  239. data/spec/unit/persistence/dynamoid_persistence_multiple_spec.rb +135 -0
  240. data/spec/unit/persistence/dynamoid_persistence_spec.rb +84 -0
  241. data/spec/unit/persistence/mongoid_persistence_multiple_spec.rb +200 -0
  242. data/spec/unit/persistence/mongoid_persistence_spec.rb +165 -0
  243. data/spec/unit/persistence/no_brainer_persistence_multiple_spec.rb +198 -0
  244. data/spec/unit/persistence/no_brainer_persistence_spec.rb +158 -0
  245. data/spec/unit/persistence/redis_persistence_multiple_spec.rb +88 -0
  246. data/spec/unit/persistence/redis_persistence_spec.rb +53 -0
  247. data/spec/unit/persistence/sequel_persistence_multiple_spec.rb +148 -0
  248. data/spec/unit/persistence/sequel_persistence_spec.rb +368 -0
  249. data/spec/unit/readme_spec.rb +41 -0
  250. data/spec/unit/reloading_spec.rb +15 -0
  251. data/spec/unit/rspec_matcher_spec.rb +88 -0
  252. data/spec/unit/simple_custom_example_spec.rb +39 -0
  253. data/spec/unit/simple_example_spec.rb +57 -0
  254. data/spec/unit/simple_multiple_example_spec.rb +91 -0
  255. data/spec/unit/state_spec.rb +89 -0
  256. data/spec/unit/states_on_one_line_example_spec.rb +16 -0
  257. data/spec/unit/subclassing_multiple_spec.rb +74 -0
  258. data/spec/unit/subclassing_spec.rb +46 -0
  259. data/spec/unit/transition_spec.rb +436 -0
  260. data/test/minitest_helper.rb +57 -0
  261. data/test/unit/minitest_matcher_test.rb +80 -0
  262. metadata +609 -0
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'subclassing' do
4
+
5
+ it 'should have the parent states' do
6
+ SuperClass.aasm.states.each do |state|
7
+ expect(SubClassWithMoreStates.aasm.states).to include(state)
8
+ end
9
+ expect(SubClass.aasm.states).to eq(SuperClass.aasm.states)
10
+ end
11
+
12
+ it 'should not add the child states to the parent machine' do
13
+ expect(SuperClass.aasm.states).not_to include(:foo)
14
+ end
15
+
16
+ it 'should have the same events as its parent' do
17
+ expect(SubClass.aasm.events).to eq(SuperClass.aasm.events)
18
+ end
19
+
20
+ it 'should know how to respond to question methods' do
21
+ expect(SubClass.new.may_foo?).to be_truthy
22
+ end
23
+
24
+ it 'should not break if I call methods from super class' do
25
+ son = SubClass.new
26
+ son.update_state
27
+ expect(son.aasm.current_state).to eq(:ended)
28
+ end
29
+
30
+ it 'should allow the child to modify its state machine' do
31
+ son = SubClass.new
32
+ expect(son.called_after).to eq(nil)
33
+ son.foo
34
+ expect(son.called_after).to eq(true)
35
+ global_callbacks = SubClass.aasm.state_machine.global_callbacks
36
+ expect(global_callbacks).to_not be_empty
37
+ expect(global_callbacks[:after_all_transitions]).to eq :after_all_event
38
+ end
39
+
40
+ it 'should not modify the parent state machine' do
41
+ super_class_event = SuperClass.aasm.events.select { |event| event.name == :foo }.first
42
+ expect(super_class_event.options).to be_empty
43
+ expect(SuperClass.aasm.state_machine.global_callbacks).to be_empty
44
+ end
45
+
46
+ end
@@ -0,0 +1,436 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'transitions' do
4
+
5
+ it 'should raise an exception when whiny' do
6
+ process = ProcessWithNewDsl.new
7
+ expect { process.stop! }.to raise_error do |err|
8
+ expect(err.class).to eql(AASM::InvalidTransition)
9
+ expect(err.message).to eql("Event 'stop' cannot transition from 'sleeping'.")
10
+ expect(err.object).to eql(process)
11
+ expect(err.event_name).to eql(:stop)
12
+ end
13
+ expect(process).to be_sleeping
14
+ end
15
+
16
+ it 'should not raise an exception when not whiny' do
17
+ silencer = Silencer.new
18
+ expect(silencer.smile!).to be_falsey
19
+ expect(silencer).to be_silent
20
+ end
21
+
22
+ it 'should not raise an exception when superclass not whiny' do
23
+ sub = SubClassing.new
24
+ expect(sub.smile!).to be_falsey
25
+ expect(sub).to be_silent
26
+ end
27
+
28
+ it 'should not raise an exception when from is nil even if whiny' do
29
+ silencer = Silencer.new
30
+ expect(silencer.smile_any!).to be_truthy
31
+ expect(silencer).to be_smiling
32
+ end
33
+
34
+ it 'should call the block on success' do
35
+ silencer = Silencer.new
36
+ success = false
37
+ expect {
38
+ silencer.smile_any! do
39
+ success = true
40
+ end
41
+ }.to change { success }.to(true)
42
+ end
43
+
44
+ it 'should not call the block on failure' do
45
+ silencer = Silencer.new
46
+ success = false
47
+ expect {
48
+ silencer.smile! do
49
+ success = true
50
+ end
51
+ }.not_to change { success }
52
+ end
53
+
54
+ end
55
+
56
+ describe AASM::Core::Transition do
57
+ let(:state_machine) { AASM::StateMachine.new(:name) }
58
+ let(:event) { AASM::Core::Event.new(:event, state_machine) }
59
+
60
+ it 'should set from, to, and opts attr readers' do
61
+ opts = {:from => 'foo', :to => 'bar', :guard => 'g'}
62
+ st = AASM::Core::Transition.new(event, opts)
63
+
64
+ expect(st.from).to eq(opts[:from])
65
+ expect(st.to).to eq(opts[:to])
66
+ expect(st.opts).to eq(opts)
67
+ end
68
+
69
+ it 'should set on_transition with deprecation warning' do
70
+ opts = {:from => 'foo', :to => 'bar'}
71
+ st = AASM::Core::Transition.allocate
72
+ expect(st).to receive(:warn).with('[DEPRECATION] :on_transition is deprecated, use :after instead')
73
+
74
+ st.send :initialize, event, opts do
75
+ guard :gg
76
+ on_transition :after_callback
77
+ end
78
+
79
+ expect(st.opts[:after]).to eql [:after_callback]
80
+ end
81
+
82
+ it 'should set after, guard and success from dsl' do
83
+ opts = {:from => 'foo', :to => 'bar', :guard => 'g'}
84
+ st = AASM::Core::Transition.new(event, opts) do
85
+ guard :gg
86
+ after :after_callback
87
+ success :after_persist
88
+ end
89
+
90
+ expect(st.opts[:guard]).to eql ['g', :gg]
91
+ expect(st.opts[:after]).to eql [:after_callback] # TODO fix this bad code coupling
92
+ expect(st.opts[:success]).to eql [:after_persist] # TODO fix this bad code coupling
93
+ end
94
+
95
+ it 'should pass equality check if from and to are the same' do
96
+ opts = {:from => 'foo', :to => 'bar', :guard => 'g'}
97
+ st = AASM::Core::Transition.new(event, opts)
98
+
99
+ obj = double('object')
100
+ allow(obj).to receive(:from).and_return(opts[:from])
101
+ allow(obj).to receive(:to).and_return(opts[:to])
102
+
103
+ expect(st).to eq(obj)
104
+ end
105
+
106
+ it 'should fail equality check if from are not the same' do
107
+ opts = {:from => 'foo', :to => 'bar', :guard => 'g'}
108
+ st = AASM::Core::Transition.new(event, opts)
109
+
110
+ obj = double('object')
111
+ allow(obj).to receive(:from).and_return('blah')
112
+ allow(obj).to receive(:to).and_return(opts[:to])
113
+
114
+ expect(st).not_to eq(obj)
115
+ end
116
+
117
+ it 'should fail equality check if to are not the same' do
118
+ opts = {:from => 'foo', :to => 'bar', :guard => 'g'}
119
+ st = AASM::Core::Transition.new(event, opts)
120
+
121
+ obj = double('object')
122
+ allow(obj).to receive(:from).and_return(opts[:from])
123
+ allow(obj).to receive(:to).and_return('blah')
124
+
125
+ expect(st).not_to eq(obj)
126
+ end
127
+ end
128
+
129
+ describe AASM::Core::Transition, '- when performing guard checks' do
130
+ let(:state_machine) { AASM::StateMachine.new(:name) }
131
+ let(:event) { AASM::Core::Event.new(:event, state_machine) }
132
+
133
+ it 'should return true of there is no guard' do
134
+ opts = {:from => 'foo', :to => 'bar'}
135
+ st = AASM::Core::Transition.new(event, opts)
136
+
137
+ expect(st.allowed?(nil)).to be_truthy
138
+ end
139
+
140
+ it 'should call the method on the object if guard is a symbol' do
141
+ opts = {:from => 'foo', :to => 'bar', :guard => :test}
142
+ st = AASM::Core::Transition.new(event, opts)
143
+
144
+ obj = double('object')
145
+ expect(obj).to receive(:test)
146
+
147
+ expect(st.allowed?(obj)).to be false
148
+ end
149
+
150
+ it 'should add the name of the failed method calls to the failures instance var' do
151
+ opts = {:from => 'foo', :to => 'bar', :guard => :test}
152
+ st = AASM::Core::Transition.new(event, opts)
153
+
154
+ obj = double('object')
155
+ expect(obj).to receive(:test)
156
+
157
+ st.allowed?(obj)
158
+ expect(st.failures).to eq [:test]
159
+ end
160
+
161
+ it 'should call the method on the object if unless is a symbol' do
162
+ opts = {:from => 'foo', :to => 'bar', :unless => :test}
163
+ st = AASM::Core::Transition.new(event, opts)
164
+
165
+ obj = double('object')
166
+ expect(obj).to receive(:test)
167
+
168
+ expect(st.allowed?(obj)).to be true
169
+ end
170
+
171
+ it 'should call the method on the object if guard is a string' do
172
+ opts = {:from => 'foo', :to => 'bar', :guard => 'test'}
173
+ st = AASM::Core::Transition.new(event, opts)
174
+
175
+ obj = double('object')
176
+ expect(obj).to receive(:test)
177
+
178
+ expect(st.allowed?(obj)).to be false
179
+ end
180
+
181
+ it 'should call the method on the object if unless is a string' do
182
+ opts = {:from => 'foo', :to => 'bar', :unless => 'test'}
183
+ st = AASM::Core::Transition.new(event, opts)
184
+
185
+ obj = double('object')
186
+ expect(obj).to receive(:test)
187
+
188
+ expect(st.allowed?(obj)).to be true
189
+ end
190
+
191
+ it 'should call the proc passing the object if the guard is a proc' do
192
+ opts = {:from => 'foo', :to => 'bar', :guard => Proc.new { test }}
193
+ st = AASM::Core::Transition.new(event, opts)
194
+
195
+ obj = double('object')
196
+ expect(obj).to receive(:test)
197
+
198
+ expect(st.allowed?(obj)).to be false
199
+ end
200
+ end
201
+
202
+ describe AASM::Core::Transition, '- when executing the transition with a Proc' do
203
+ let(:state_machine) { AASM::StateMachine.new(:name) }
204
+ let(:event) { AASM::Core::Event.new(:event, state_machine) }
205
+
206
+ it 'should call a Proc on the object with args' do
207
+ opts = {:from => 'foo', :to => 'bar', :after => Proc.new {|a| test(a) }}
208
+ st = AASM::Core::Transition.new(event, opts)
209
+ args = {:arg1 => '1', :arg2 => '2'}
210
+ obj = double('object', :aasm => 'aasm')
211
+
212
+ expect(obj).to receive(:test).with(args)
213
+
214
+ st.execute(obj, args)
215
+ end
216
+
217
+ it 'should call a Proc on the object without args' do
218
+ # in order to test that the Proc has been called, we make sure
219
+ # that after running the :after callback the prc_object is set
220
+ prc_object = nil
221
+ prc = Proc.new { prc_object = self }
222
+
223
+ opts = {:from => 'foo', :to => 'bar', :after => prc }
224
+ st = AASM::Core::Transition.new(event, opts)
225
+ args = {:arg1 => '1', :arg2 => '2'}
226
+ obj = double('object', :aasm => 'aasm')
227
+
228
+ st.execute(obj, args)
229
+ expect(prc_object).to eql obj
230
+ end
231
+ end
232
+
233
+ describe AASM::Core::Transition, '- when executing the transition with an :after method call' do
234
+ let(:state_machine) { AASM::StateMachine.new(:name) }
235
+ let(:event) { AASM::Core::Event.new(:event, state_machine) }
236
+
237
+ it 'should accept a String for the method name' do
238
+ opts = {:from => 'foo', :to => 'bar', :after => 'test'}
239
+ st = AASM::Core::Transition.new(event, opts)
240
+ args = {:arg1 => '1', :arg2 => '2'}
241
+ obj = double('object', :aasm => 'aasm')
242
+
243
+ expect(obj).to receive(:test)
244
+
245
+ st.execute(obj, args)
246
+ end
247
+
248
+ it 'should accept a Symbol for the method name' do
249
+ opts = {:from => 'foo', :to => 'bar', :after => :test}
250
+ st = AASM::Core::Transition.new(event, opts)
251
+ args = {:arg1 => '1', :arg2 => '2'}
252
+ obj = double('object', :aasm => 'aasm')
253
+
254
+ expect(obj).to receive(:test)
255
+
256
+ st.execute(obj, args)
257
+ end
258
+
259
+ it 'should pass args if the target method accepts them' do
260
+ opts = {:from => 'foo', :to => 'bar', :after => :test}
261
+ st = AASM::Core::Transition.new(event, opts)
262
+ args = {:arg1 => '1', :arg2 => '2'}
263
+ obj = double('object', :aasm => 'aasm')
264
+
265
+ def obj.test(args)
266
+ "arg1: #{args[:arg1]} arg2: #{args[:arg2]}"
267
+ end
268
+
269
+ return_value = st.execute(obj, args)
270
+
271
+ expect(return_value).to eq('arg1: 1 arg2: 2')
272
+ end
273
+
274
+ it 'should NOT pass args if the target method does NOT accept them' do
275
+ opts = {:from => 'foo', :to => 'bar', :after => :test}
276
+ st = AASM::Core::Transition.new(event, opts)
277
+ args = {:arg1 => '1', :arg2 => '2'}
278
+ obj = double('object', :aasm => 'aasm')
279
+
280
+ def obj.test
281
+ 'success'
282
+ end
283
+
284
+ return_value = st.execute(obj, args)
285
+
286
+ expect(return_value).to eq('success')
287
+ end
288
+
289
+ it 'should allow accessing the from_state and the to_state' do
290
+ opts = {:from => 'foo', :to => 'bar', :after => :test}
291
+ transition = AASM::Core::Transition.new(event, opts)
292
+ args = {:arg1 => '1', :arg2 => '2'}
293
+ obj = double('object', :aasm => AASM::InstanceBase.new('object'))
294
+
295
+ def obj.test(args)
296
+ "from: #{aasm.from_state} to: #{aasm.to_state}"
297
+ end
298
+
299
+ return_value = transition.execute(obj, args)
300
+
301
+ expect(return_value).to eq('from: foo to: bar')
302
+ end
303
+
304
+ end
305
+
306
+ describe AASM::Core::Transition, '- when executing the transition with a Class' do
307
+ let(:state_machine) { AASM::StateMachine.new(:name) }
308
+ let(:event) { AASM::Core::Event.new(:event, state_machine) }
309
+
310
+ class AfterTransitionClass
311
+ def initialize(record)
312
+ @record = record
313
+ end
314
+
315
+ def call
316
+ "from: #{@record.aasm.from_state} to: #{@record.aasm.to_state}"
317
+ end
318
+ end
319
+
320
+ class AfterTransitionClassWithArgs
321
+ def initialize(record, args)
322
+ @record = record
323
+ @args = args
324
+ end
325
+
326
+ def call
327
+ "arg1: #{@args[:arg1]}, arg2: #{@args[:arg2]}"
328
+ end
329
+ end
330
+
331
+ class AfterTransitionClassWithoutArgs
332
+ def call
333
+ 'success'
334
+ end
335
+ end
336
+
337
+ it 'passes the record to the initialize method on the class to give access to the from_state and to_state' do
338
+ opts = {:from => 'foo', :to => 'bar', :after => AfterTransitionClass}
339
+ transition = AASM::Core::Transition.new(event, opts)
340
+ obj = double('object', :aasm => AASM::InstanceBase.new('object'))
341
+
342
+ return_value = transition.execute(obj)
343
+
344
+ expect(return_value).to eq('from: foo to: bar')
345
+ end
346
+
347
+ it 'should pass args to the initialize method on the class if it accepts them' do
348
+ opts = {:from => 'foo', :to => 'bar', :after => AfterTransitionClassWithArgs}
349
+ st = AASM::Core::Transition.new(event, opts)
350
+ args = {:arg1 => '1', :arg2 => '2'}
351
+ obj = double('object', :aasm => 'aasm')
352
+
353
+ return_value = st.execute(obj, args)
354
+
355
+ expect(return_value).to eq('arg1: 1, arg2: 2')
356
+ end
357
+
358
+ it 'should NOT pass args if the call method of the class if it does NOT accept them' do
359
+ opts = {:from => 'foo', :to => 'bar', :after => AfterTransitionClassWithoutArgs}
360
+ st = AASM::Core::Transition.new(event, opts)
361
+ obj = double('object', :aasm => 'aasm')
362
+
363
+ return_value = st.execute(obj)
364
+
365
+ expect(return_value).to eq('success')
366
+ end
367
+ end
368
+
369
+ describe AASM::Core::Transition, '- when invoking the transition :success method call' do
370
+ let(:state_machine) { AASM::StateMachine.new(:name) }
371
+ let(:event) { AASM::Core::Event.new(:event, state_machine) }
372
+
373
+ it 'should accept a String for the method name' do
374
+ opts = {:from => 'foo', :to => 'bar', :success => 'test'}
375
+ st = AASM::Core::Transition.new(event, opts)
376
+ args = {:arg1 => '1', :arg2 => '2'}
377
+ obj = double('object', :aasm => 'aasm')
378
+
379
+ expect(obj).to receive(:test)
380
+
381
+ st.invoke_success_callbacks(obj, args)
382
+ end
383
+
384
+ it 'should accept a Symbol for the method name' do
385
+ opts = {:from => 'foo', :to => 'bar', :success => :test}
386
+ st = AASM::Core::Transition.new(event, opts)
387
+ args = {:arg1 => '1', :arg2 => '2'}
388
+ obj = double('object', :aasm => 'aasm')
389
+
390
+ expect(obj).to receive(:test)
391
+
392
+ st.invoke_success_callbacks(obj, args)
393
+ end
394
+
395
+ it 'should accept a Array for the method name' do
396
+ opts = {:from => 'foo', :to => 'bar', :success => [:test1, :test2]}
397
+ st = AASM::Core::Transition.new(event, opts)
398
+ args = {:arg1 => '1', :arg2 => '2'}
399
+ obj = double('object', :aasm => 'aasm')
400
+
401
+ expect(obj).to receive(:test1)
402
+ expect(obj).to receive(:test2)
403
+
404
+ st.invoke_success_callbacks(obj, args)
405
+ end
406
+
407
+ it 'should pass args if the target method accepts them' do
408
+ opts = {:from => 'foo', :to => 'bar', :success => :test}
409
+ st = AASM::Core::Transition.new(event, opts)
410
+ args = {:arg1 => '1', :arg2 => '2'}
411
+ obj = double('object', :aasm => 'aasm')
412
+
413
+ def obj.test(args)
414
+ "arg1: #{args[:arg1]} arg2: #{args[:arg2]}"
415
+ end
416
+
417
+ return_value = st.invoke_success_callbacks(obj, args)
418
+
419
+ expect(return_value).to eq('arg1: 1 arg2: 2')
420
+ end
421
+
422
+ it 'should NOT pass args if the target method does NOT accept them' do
423
+ opts = {:from => 'foo', :to => 'bar', :success => :test}
424
+ st = AASM::Core::Transition.new(event, opts)
425
+ args = {:arg1 => '1', :arg2 => '2'}
426
+ obj = double('object', :aasm => 'aasm')
427
+
428
+ def obj.test
429
+ 'success'
430
+ end
431
+
432
+ return_value = st.invoke_success_callbacks(obj, args)
433
+
434
+ expect(return_value).to eq('success')
435
+ end
436
+ end