aasm 4.11.1 → 5.2.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 (194) hide show
  1. checksums.yaml +5 -5
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +27 -0
  3. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  4. data/.travis.yml +56 -23
  5. data/Appraisals +67 -0
  6. data/CHANGELOG.md +112 -0
  7. data/CONTRIBUTING.md +24 -0
  8. data/Dockerfile +44 -0
  9. data/Gemfile +3 -21
  10. data/Gemfile.lock_old +151 -0
  11. data/LICENSE +1 -1
  12. data/README.md +540 -139
  13. data/Rakefile +6 -1
  14. data/TESTING.md +25 -0
  15. data/aasm.gemspec +5 -0
  16. data/docker-compose.yml +40 -0
  17. data/gemfiles/norails.gemfile +10 -0
  18. data/gemfiles/rails_4.2.gemfile +13 -11
  19. data/gemfiles/rails_4.2_mongoid_5.gemfile +8 -11
  20. data/gemfiles/rails_4.2_nobrainer.gemfile +9 -0
  21. data/gemfiles/rails_5.0.gemfile +11 -18
  22. data/gemfiles/rails_5.0_nobrainer.gemfile +9 -0
  23. data/gemfiles/rails_5.1.gemfile +14 -0
  24. data/gemfiles/rails_5.2.gemfile +14 -0
  25. data/lib/aasm/aasm.rb +40 -29
  26. data/lib/aasm/base.rb +61 -11
  27. data/lib/aasm/configuration.rb +10 -0
  28. data/lib/aasm/core/event.rb +45 -37
  29. data/lib/aasm/core/invoker.rb +129 -0
  30. data/lib/aasm/core/invokers/base_invoker.rb +75 -0
  31. data/lib/aasm/core/invokers/class_invoker.rb +52 -0
  32. data/lib/aasm/core/invokers/literal_invoker.rb +47 -0
  33. data/lib/aasm/core/invokers/proc_invoker.rb +59 -0
  34. data/lib/aasm/core/state.rb +22 -13
  35. data/lib/aasm/core/transition.rb +17 -69
  36. data/lib/aasm/dsl_helper.rb +24 -22
  37. data/lib/aasm/errors.rb +4 -6
  38. data/lib/aasm/instance_base.rb +22 -4
  39. data/lib/aasm/localizer.rb +13 -3
  40. data/lib/aasm/minitest/allow_event.rb +13 -0
  41. data/lib/aasm/minitest/allow_transition_to.rb +13 -0
  42. data/lib/aasm/minitest/have_state.rb +13 -0
  43. data/lib/aasm/minitest/transition_from.rb +21 -0
  44. data/lib/aasm/minitest.rb +5 -0
  45. data/lib/aasm/minitest_spec.rb +15 -0
  46. data/lib/aasm/persistence/active_record_persistence.rb +49 -105
  47. data/lib/aasm/persistence/base.rb +20 -5
  48. data/lib/aasm/persistence/core_data_query_persistence.rb +2 -1
  49. data/lib/aasm/persistence/dynamoid_persistence.rb +1 -1
  50. data/lib/aasm/persistence/mongoid_persistence.rb +26 -32
  51. data/lib/aasm/persistence/no_brainer_persistence.rb +105 -0
  52. data/lib/aasm/persistence/orm.rb +154 -0
  53. data/lib/aasm/persistence/plain_persistence.rb +2 -1
  54. data/lib/aasm/persistence/redis_persistence.rb +16 -11
  55. data/lib/aasm/persistence/sequel_persistence.rb +36 -64
  56. data/lib/aasm/persistence.rb +3 -3
  57. data/lib/aasm/rspec/allow_event.rb +5 -1
  58. data/lib/aasm/rspec/allow_transition_to.rb +5 -1
  59. data/lib/aasm/rspec/transition_from.rb +5 -1
  60. data/lib/aasm/state_machine.rb +4 -2
  61. data/lib/aasm/state_machine_store.rb +5 -2
  62. data/lib/aasm/version.rb +1 -1
  63. data/lib/aasm.rb +5 -2
  64. data/lib/generators/aasm/orm_helpers.rb +6 -0
  65. data/lib/generators/active_record/aasm_generator.rb +3 -1
  66. data/lib/generators/active_record/templates/migration.rb +1 -1
  67. data/lib/generators/active_record/templates/migration_existing.rb +1 -1
  68. data/lib/generators/nobrainer/aasm_generator.rb +28 -0
  69. data/lib/motion-aasm.rb +3 -1
  70. data/spec/database.rb +20 -7
  71. data/spec/en.yml +0 -3
  72. data/spec/generators/active_record_generator_spec.rb +49 -40
  73. data/spec/generators/mongoid_generator_spec.rb +4 -6
  74. data/spec/generators/no_brainer_generator_spec.rb +29 -0
  75. data/spec/{en_deprecated_style.yml → localizer_test_model_deprecated_style.yml} +6 -3
  76. data/spec/localizer_test_model_new_style.yml +11 -0
  77. data/spec/models/active_record/active_record_callback.rb +93 -0
  78. data/spec/models/active_record/complex_active_record_example.rb +5 -1
  79. data/spec/models/active_record/instance_level_skip_validation_example.rb +19 -0
  80. data/spec/models/{invalid_persistor.rb → active_record/invalid_persistor.rb} +0 -2
  81. data/spec/models/active_record/localizer_test_model.rb +11 -3
  82. data/spec/models/active_record/namespaced.rb +16 -0
  83. data/spec/models/active_record/person.rb +23 -0
  84. data/spec/models/{silent_persistor.rb → active_record/silent_persistor.rb} +0 -2
  85. data/spec/models/active_record/simple_new_dsl.rb +15 -0
  86. data/spec/models/active_record/timestamp_example.rb +16 -0
  87. data/spec/models/{transactor.rb → active_record/transactor.rb} +25 -2
  88. data/spec/models/{validator.rb → active_record/validator.rb} +0 -2
  89. data/spec/models/active_record/work.rb +3 -0
  90. data/spec/models/{worker.rb → active_record/worker.rb} +0 -0
  91. data/spec/models/callbacks/basic.rb +5 -2
  92. data/spec/models/callbacks/with_state_arg.rb +5 -1
  93. data/spec/models/callbacks/with_state_arg_multiple.rb +4 -1
  94. data/spec/models/default_state.rb +1 -1
  95. data/spec/models/guard_arguments_check.rb +17 -0
  96. data/spec/models/guard_with_params.rb +1 -1
  97. data/spec/models/guardian_without_from_specified.rb +18 -0
  98. data/spec/models/mongoid/invalid_persistor_mongoid.rb +39 -0
  99. data/spec/models/mongoid/silent_persistor_mongoid.rb +39 -0
  100. data/spec/models/mongoid/timestamp_example_mongoid.rb +20 -0
  101. data/spec/models/mongoid/validator_mongoid.rb +100 -0
  102. data/spec/models/multiple_transitions_that_differ_only_by_guard.rb +31 -0
  103. data/spec/models/namespaced_multiple_example.rb +14 -0
  104. data/spec/models/nobrainer/complex_no_brainer_example.rb +36 -0
  105. data/spec/models/nobrainer/invalid_persistor_no_brainer.rb +39 -0
  106. data/spec/models/nobrainer/no_scope_no_brainer.rb +21 -0
  107. data/spec/models/nobrainer/nobrainer_relationships.rb +25 -0
  108. data/spec/models/nobrainer/silent_persistor_no_brainer.rb +39 -0
  109. data/spec/models/nobrainer/simple_new_dsl_nobrainer.rb +25 -0
  110. data/spec/models/{mongo_mapper/simple_mongo_mapper.rb → nobrainer/simple_no_brainer.rb} +8 -8
  111. data/spec/models/nobrainer/validator_no_brainer.rb +98 -0
  112. data/spec/models/parametrised_event.rb +7 -0
  113. data/spec/models/{mongo_mapper/complex_mongo_mapper_example.rb → redis/complex_redis_example.rb} +8 -5
  114. data/spec/models/redis/redis_multiple.rb +20 -0
  115. data/spec/models/redis/redis_simple.rb +20 -0
  116. data/spec/models/sequel/complex_sequel_example.rb +4 -3
  117. data/spec/models/sequel/invalid_persistor.rb +52 -0
  118. data/spec/models/sequel/sequel_multiple.rb +13 -13
  119. data/spec/models/sequel/sequel_simple.rb +13 -12
  120. data/spec/models/sequel/silent_persistor.rb +50 -0
  121. data/spec/models/sequel/transactor.rb +112 -0
  122. data/spec/models/sequel/validator.rb +93 -0
  123. data/spec/models/sequel/worker.rb +12 -0
  124. data/spec/models/simple_example.rb +8 -0
  125. data/spec/models/simple_example_with_guard_args.rb +17 -0
  126. data/spec/models/simple_multiple_example.rb +12 -0
  127. data/spec/models/sub_class.rb +34 -0
  128. data/spec/models/timestamps_example.rb +19 -0
  129. data/spec/models/timestamps_with_named_machine_example.rb +13 -0
  130. data/spec/spec_helper.rb +15 -33
  131. data/spec/spec_helpers/active_record.rb +8 -0
  132. data/spec/spec_helpers/dynamoid.rb +35 -0
  133. data/spec/spec_helpers/mongoid.rb +26 -0
  134. data/spec/spec_helpers/nobrainer.rb +15 -0
  135. data/spec/spec_helpers/redis.rb +18 -0
  136. data/spec/spec_helpers/remove_warnings.rb +1 -0
  137. data/spec/spec_helpers/sequel.rb +7 -0
  138. data/spec/unit/abstract_class_spec.rb +27 -0
  139. data/spec/unit/api_spec.rb +79 -72
  140. data/spec/unit/callback_multiple_spec.rb +7 -3
  141. data/spec/unit/callbacks_spec.rb +37 -2
  142. data/spec/unit/complex_example_spec.rb +12 -3
  143. data/spec/unit/complex_multiple_example_spec.rb +20 -4
  144. data/spec/unit/event_multiple_spec.rb +1 -1
  145. data/spec/unit/event_spec.rb +29 -4
  146. data/spec/unit/exception_spec.rb +1 -1
  147. data/spec/unit/guard_arguments_check_spec.rb +9 -0
  148. data/spec/unit/guard_spec.rb +17 -0
  149. data/spec/unit/guard_with_params_spec.rb +4 -0
  150. data/spec/unit/guard_without_from_specified_spec.rb +10 -0
  151. data/spec/unit/inspection_multiple_spec.rb +9 -5
  152. data/spec/unit/inspection_spec.rb +7 -3
  153. data/spec/unit/invoker_spec.rb +189 -0
  154. data/spec/unit/invokers/base_invoker_spec.rb +72 -0
  155. data/spec/unit/invokers/class_invoker_spec.rb +95 -0
  156. data/spec/unit/invokers/literal_invoker_spec.rb +86 -0
  157. data/spec/unit/invokers/proc_invoker_spec.rb +86 -0
  158. data/spec/unit/localizer_spec.rb +85 -52
  159. data/spec/unit/multiple_transitions_that_differ_only_by_guard_spec.rb +14 -0
  160. data/spec/unit/namespaced_multiple_example_spec.rb +22 -0
  161. data/spec/unit/override_warning_spec.rb +8 -0
  162. data/spec/unit/persistence/active_record_persistence_multiple_spec.rb +468 -447
  163. data/spec/unit/persistence/active_record_persistence_spec.rb +639 -486
  164. data/spec/unit/persistence/dynamoid_persistence_multiple_spec.rb +4 -9
  165. data/spec/unit/persistence/dynamoid_persistence_spec.rb +4 -9
  166. data/spec/unit/persistence/mongoid_persistence_multiple_spec.rb +83 -13
  167. data/spec/unit/persistence/mongoid_persistence_spec.rb +97 -13
  168. data/spec/unit/persistence/no_brainer_persistence_multiple_spec.rb +198 -0
  169. data/spec/unit/persistence/no_brainer_persistence_spec.rb +158 -0
  170. data/spec/unit/persistence/redis_persistence_multiple_spec.rb +88 -0
  171. data/spec/unit/persistence/redis_persistence_spec.rb +8 -32
  172. data/spec/unit/persistence/sequel_persistence_multiple_spec.rb +6 -11
  173. data/spec/unit/persistence/sequel_persistence_spec.rb +278 -10
  174. data/spec/unit/rspec_matcher_spec.rb +9 -0
  175. data/spec/unit/simple_example_spec.rb +15 -0
  176. data/spec/unit/simple_multiple_example_spec.rb +28 -0
  177. data/spec/unit/state_spec.rb +23 -7
  178. data/spec/unit/subclassing_multiple_spec.rb +37 -2
  179. data/spec/unit/subclassing_spec.rb +17 -2
  180. data/spec/unit/timestamps_spec.rb +32 -0
  181. data/spec/unit/transition_spec.rb +1 -1
  182. data/test/minitest_helper.rb +57 -0
  183. data/test/unit/minitest_matcher_test.rb +80 -0
  184. metadata +213 -37
  185. data/callbacks.txt +0 -51
  186. data/gemfiles/rails_3.2_stable.gemfile +0 -15
  187. data/gemfiles/rails_4.0.gemfile +0 -16
  188. data/gemfiles/rails_4.0_mongo_mapper.gemfile +0 -16
  189. data/gemfiles/rails_4.2_mongo_mapper.gemfile +0 -17
  190. data/lib/aasm/persistence/mongo_mapper_persistence.rb +0 -163
  191. data/spec/models/mongo_mapper/no_scope_mongo_mapper.rb +0 -21
  192. data/spec/models/mongo_mapper/simple_new_dsl_mongo_mapper.rb +0 -25
  193. data/spec/unit/persistence/mongo_mapper_persistence_multiple_spec.rb +0 -149
  194. data/spec/unit/persistence/mongo_mapper_persistence_spec.rb +0 -96
@@ -1,614 +1,635 @@
1
- require 'active_record'
2
1
  require 'spec_helper'
3
- Dir[File.dirname(__FILE__) + "/../../models/active_record/*.rb"].sort.each do |f|
4
- require File.expand_path(f)
5
- end
6
-
7
- load_schema
8
-
9
- # if you want to see the statements while running the spec enable the following line
10
- # require 'logger'
11
- # ActiveRecord::Base.logger = Logger.new(STDERR)
12
2
 
13
- describe "instance methods" do
14
- let(:gate) {MultipleGate.new}
3
+ if defined?(ActiveRecord)
15
4
 
16
- it "should respond to aasm persistence methods" do
17
- expect(gate).to respond_to(:aasm_read_state)
18
- expect(gate).to respond_to(:aasm_write_state)
19
- expect(gate).to respond_to(:aasm_write_state_without_persistence)
5
+ Dir[File.dirname(__FILE__) + "/../../models/active_record/*.rb"].sort.each do |f|
6
+ require File.expand_path(f)
20
7
  end
21
8
 
22
- describe "aasm_column_looks_like_enum" do
23
- subject { lambda{ gate.send(:aasm_column_looks_like_enum, :left) } }
9
+ load_schema
24
10
 
25
- let(:column_name) { "value" }
26
- let(:columns_hash) { Hash[column_name, column] }
27
-
28
- before :each do
29
- allow(gate.class.aasm(:left)).to receive(:attribute_name).and_return(column_name.to_sym)
30
- allow(gate.class).to receive(:columns_hash).and_return(columns_hash)
31
- end
11
+ # if you want to see the statements while running the spec enable the following line
12
+ # require 'logger'
13
+ # ActiveRecord::Base.logger = Logger.new(STDERR)
32
14
 
33
- context "when AASM column has integer type" do
34
- let(:column) { double(Object, type: :integer) }
15
+ describe "instance methods" do
16
+ let(:gate) {MultipleGate.new}
35
17
 
36
- it "returns true" do
37
- expect(subject.call).to be_truthy
38
- end
18
+ it "should respond to aasm persistence methods" do
19
+ expect(gate).to respond_to(:aasm_read_state)
20
+ expect(gate).to respond_to(:aasm_write_state)
21
+ expect(gate).to respond_to(:aasm_write_state_without_persistence)
39
22
  end
40
23
 
41
- context "when AASM column has string type" do
42
- let(:column) { double(Object, type: :string) }
24
+ describe "aasm_column_looks_like_enum" do
25
+ subject { lambda{ gate.send(:aasm_column_looks_like_enum, :left) } }
43
26
 
44
- it "returns false" do
45
- expect(subject.call).to be_falsey
46
- end
47
- end
48
- end
27
+ let(:column_name) { "value" }
28
+ let(:columns_hash) { Hash[column_name, column] }
49
29
 
50
- describe "aasm_guess_enum_method" do
51
- subject { lambda{ gate.send(:aasm_guess_enum_method, :left) } }
30
+ before :each do
31
+ allow(gate.class.aasm(:left)).to receive(:attribute_name).and_return(column_name.to_sym)
32
+ allow(gate.class).to receive(:columns_hash).and_return(columns_hash)
33
+ end
52
34
 
53
- before :each do
54
- allow(gate.class.aasm(:left)).to receive(:attribute_name).and_return(:value)
55
- end
35
+ context "when AASM column has integer type" do
36
+ let(:column) { double(Object, type: :integer) }
56
37
 
57
- it "pluralizes AASM column name" do
58
- expect(subject.call).to eq :values
59
- end
60
- end
38
+ it "returns true" do
39
+ expect(subject.call).to be_truthy
40
+ end
41
+ end
61
42
 
62
- describe "aasm_enum" do
63
- context "when AASM enum setting contains an explicit enum method name" do
64
- let(:with_enum) { MultipleWithEnum.new }
43
+ context "when AASM column has string type" do
44
+ let(:column) { double(Object, type: :string) }
65
45
 
66
- it "returns whatever value was set in AASM config" do
67
- expect(with_enum.send(:aasm_enum, :left)).to eq :test
46
+ it "returns false" do
47
+ expect(subject.call).to be_falsey
48
+ end
68
49
  end
69
50
  end
70
51
 
71
- context "when AASM enum setting is simply set to true" do
72
- let(:with_true_enum) { MultipleWithTrueEnum.new }
52
+ describe "aasm_guess_enum_method" do
53
+ subject { lambda{ gate.send(:aasm_guess_enum_method, :left) } }
54
+
73
55
  before :each do
74
- allow(MultipleWithTrueEnum.aasm(:left)).to receive(:attribute_name).and_return(:value)
56
+ allow(gate.class.aasm(:left)).to receive(:attribute_name).and_return(:value)
75
57
  end
76
58
 
77
- it "infers enum method name from pluralized column name" do
78
- expect(with_true_enum.send(:aasm_enum, :left)).to eq :values
59
+ it "pluralizes AASM column name" do
60
+ expect(subject.call).to eq :values
79
61
  end
80
62
  end
81
63
 
82
- context "when AASM enum setting is explicitly disabled" do
83
- let(:with_false_enum) { MultipleWithFalseEnum.new }
64
+ describe "aasm_enum" do
65
+ context "when AASM enum setting contains an explicit enum method name" do
66
+ let(:with_enum) { MultipleWithEnum.new }
84
67
 
85
- it "returns nil" do
86
- expect(with_false_enum.send(:aasm_enum, :left)).to be_nil
87
- end
88
- end
89
-
90
- context "when AASM enum setting is not enabled" do
91
- before :each do
92
- allow(MultipleGate.aasm(:left)).to receive(:attribute_name).and_return(:value)
68
+ it "returns whatever value was set in AASM config" do
69
+ expect(with_enum.send(:aasm_enum, :left)).to eq :test
70
+ end
93
71
  end
94
72
 
95
- context "when AASM column looks like enum" do
73
+ context "when AASM enum setting is simply set to true" do
74
+ let(:with_true_enum) { MultipleWithTrueEnum.new }
96
75
  before :each do
97
- allow(gate).to receive(:aasm_column_looks_like_enum).with(:left).and_return(true)
76
+ allow(MultipleWithTrueEnum.aasm(:left)).to receive(:attribute_name).and_return(:value)
98
77
  end
99
78
 
100
79
  it "infers enum method name from pluralized column name" do
101
- expect(gate.send(:aasm_enum, :left)).to eq :values
80
+ expect(with_true_enum.send(:aasm_enum, :left)).to eq :values
102
81
  end
103
82
  end
104
83
 
105
- context "when AASM column doesn't look like enum'" do
84
+ context "when AASM enum setting is explicitly disabled" do
85
+ let(:with_false_enum) { MultipleWithFalseEnum.new }
86
+
87
+ it "returns nil" do
88
+ expect(with_false_enum.send(:aasm_enum, :left)).to be_nil
89
+ end
90
+ end
91
+
92
+ context "when AASM enum setting is not enabled" do
106
93
  before :each do
107
- allow(gate).to receive(:aasm_column_looks_like_enum)
108
- .and_return(false)
94
+ allow(MultipleGate.aasm(:left)).to receive(:attribute_name).and_return(:value)
95
+ end
96
+
97
+ context "when AASM column looks like enum" do
98
+ before :each do
99
+ allow(gate).to receive(:aasm_column_looks_like_enum).with(:left).and_return(true)
100
+ end
101
+
102
+ it "infers enum method name from pluralized column name" do
103
+ expect(gate.send(:aasm_enum, :left)).to eq :values
104
+ end
109
105
  end
110
106
 
111
- it "returns nil, as we're not using enum" do
112
- expect(gate.send(:aasm_enum, :left)).to be_nil
107
+ context "when AASM column doesn't look like enum'" do
108
+ before :each do
109
+ allow(gate).to receive(:aasm_column_looks_like_enum)
110
+ .and_return(false)
111
+ end
112
+
113
+ it "returns nil, as we're not using enum" do
114
+ expect(gate.send(:aasm_enum, :left)).to be_nil
115
+ end
113
116
  end
114
117
  end
115
- end
116
118
 
117
- if ActiveRecord::VERSION::MAJOR >= 4 && ActiveRecord::VERSION::MINOR >= 1 # won't work with Rails <= 4.1
118
- # Enum are introduced from Rails 4.1, therefore enum syntax will not work on Rails <= 4.1
119
- context "when AASM enum setting is not enabled and aasm column not present" do
119
+ if ActiveRecord::VERSION::MAJOR >= 4 && ActiveRecord::VERSION::MINOR >= 1 # won't work with Rails <= 4.1
120
+ # Enum are introduced from Rails 4.1, therefore enum syntax will not work on Rails <= 4.1
121
+ context "when AASM enum setting is not enabled and aasm column not present" do
120
122
 
121
- let(:multiple_with_enum_without_column) {MultipleWithEnumWithoutColumn.new}
123
+ let(:multiple_with_enum_without_column) {MultipleWithEnumWithoutColumn.new}
122
124
 
123
- it "should raise NoMethodError for transitions" do
124
- expect{multiple_with_enum_without_column.send(:view, :left)}.to raise_error(NoMethodError, "undefined method 'status' for MultipleWithEnumWithoutColumn")
125
+ it "should raise NoMethodError for transitions" do
126
+ expect{multiple_with_enum_without_column.send(:view, :left)}.to raise_error(NoMethodError, /undefined method .status./)
127
+ end
125
128
  end
129
+
126
130
  end
127
131
 
128
132
  end
129
133
 
130
- end
131
-
132
- context "when AASM is configured to use enum" do
133
- let(:state_sym) { :running }
134
- let(:state_code) { 2 }
135
- let(:enum_name) { :states }
136
- let(:enum) { Hash[state_sym, state_code] }
134
+ context "when AASM is configured to use enum" do
135
+ let(:state_sym) { :running }
136
+ let(:state_code) { 2 }
137
+ let(:enum_name) { :states }
138
+ let(:enum) { Hash[state_sym, state_code] }
137
139
 
138
- before :each do
139
- allow(gate).to receive(:aasm_enum).and_return(enum_name)
140
- allow(gate).to receive(:aasm_write_attribute)
141
- allow(gate).to receive(:write_attribute)
140
+ before :each do
141
+ allow(gate).to receive(:aasm_enum).and_return(enum_name)
142
+ allow(gate).to receive(:aasm_write_state_attribute)
143
+ allow(gate).to receive(:write_attribute)
142
144
 
143
- allow(MultipleGate).to receive(enum_name).and_return(enum)
144
- end
145
+ allow(MultipleGate).to receive(enum_name).and_return(enum)
146
+ end
145
147
 
146
- describe "aasm_write_state" do
147
- context "when AASM is configured to skip validations on save" do
148
- before :each do
149
- allow(gate).to receive(:aasm_skipping_validations).and_return(true)
148
+ describe "aasm_write_state" do
149
+ context "when AASM is configured to skip validations on save" do
150
+ before :each do
151
+ allow(gate).to receive(:aasm_skipping_validations).and_return(true)
152
+ end
153
+
154
+ it "passes state code instead of state symbol to update_all" do
155
+ # stub_chain does not allow us to give expectations on call
156
+ # parameters in the middle of the chain, so we need to use
157
+ # intermediate object instead.
158
+ obj = double(Object, update_all: 1)
159
+ allow(MultipleGate).to receive_message_chain(:unscoped, :where)
160
+ .and_return(obj)
161
+
162
+ gate.aasm_write_state state_sym, :left
163
+
164
+ expect(obj).to have_received(:update_all)
165
+ .with(Hash[gate.class.aasm(:left).attribute_name, state_code])
166
+ end
150
167
  end
151
168
 
152
- it "passes state code instead of state symbol to update_all" do
153
- # stub_chain does not allow us to give expectations on call
154
- # parameters in the middle of the chain, so we need to use
155
- # intermediate object instead.
156
- obj = double(Object, update_all: 1)
157
- allow(MultipleGate).to receive(:where).and_return(obj)
169
+ context "when AASM is not skipping validations" do
170
+ it "delegates state update to the helper method" do
171
+ # Let's pretend that validation is passed
172
+ allow(gate).to receive(:save).and_return(true)
158
173
 
159
- gate.aasm_write_state state_sym, :left
174
+ gate.aasm_write_state state_sym, :left
160
175
 
161
- expect(obj).to have_received(:update_all)
162
- .with(Hash[gate.class.aasm(:left).attribute_name, state_code])
176
+ expect(gate).to have_received(:aasm_write_state_attribute).with(state_sym, :left)
177
+ expect(gate).to_not have_received :write_attribute
178
+ end
163
179
  end
164
180
  end
165
181
 
166
- context "when AASM is not skipping validations" do
182
+ describe "aasm_write_state_without_persistence" do
167
183
  it "delegates state update to the helper method" do
168
- # Let's pretend that validation is passed
169
- allow(gate).to receive(:save).and_return(true)
184
+ gate.aasm_write_state_without_persistence state_sym, :left
170
185
 
171
- gate.aasm_write_state state_sym, :left
172
-
173
- expect(gate).to have_received(:aasm_write_attribute).with(state_sym, :left)
186
+ expect(gate).to have_received(:aasm_write_state_attribute).with(state_sym, :left)
174
187
  expect(gate).to_not have_received :write_attribute
175
188
  end
176
189
  end
190
+
191
+ describe "aasm_raw_attribute_value" do
192
+ it "converts state symbol to state code" do
193
+ expect(gate.send(:aasm_raw_attribute_value, state_sym))
194
+ .to eq state_code
195
+ end
196
+ end
177
197
  end
178
198
 
179
- describe "aasm_write_state_without_persistence" do
180
- it "delegates state update to the helper method" do
181
- gate.aasm_write_state_without_persistence state_sym, :left
199
+ context "when AASM is configured to use string field" do
200
+ let(:state_sym) { :running }
182
201
 
183
- expect(gate).to have_received(:aasm_write_attribute).with(state_sym, :left)
184
- expect(gate).to_not have_received :write_attribute
202
+ before :each do
203
+ allow(gate).to receive(:aasm_enum).and_return(nil)
185
204
  end
186
- end
187
205
 
188
- describe "aasm_raw_attribute_value" do
189
- it "converts state symbol to state code" do
190
- expect(gate.send(:aasm_raw_attribute_value, state_sym))
191
- .to eq state_code
206
+ describe "aasm_raw_attribute_value" do
207
+ it "converts state symbol to string" do
208
+ expect(gate.send(:aasm_raw_attribute_value, state_sym))
209
+ .to eq state_sym.to_s
210
+ end
192
211
  end
193
212
  end
194
- end
195
213
 
196
- context "when AASM is configured to use string field" do
197
- let(:state_sym) { :running }
214
+ describe "aasm_write_attribute helper method" do
215
+ let(:sym) { :sym }
216
+ let(:value) { 42 }
198
217
 
199
- before :each do
200
- allow(gate).to receive(:aasm_enum).and_return(nil)
201
- end
218
+ before :each do
219
+ allow(gate).to receive(:write_attribute)
220
+ allow(gate).to receive(:aasm_raw_attribute_value).and_return(value)
202
221
 
203
- describe "aasm_raw_attribute_value" do
204
- it "converts state symbol to string" do
205
- expect(gate.send(:aasm_raw_attribute_value, state_sym))
206
- .to eq state_sym.to_s
222
+ gate.send(:aasm_write_state_attribute, sym, :left)
207
223
  end
208
- end
209
- end
210
224
 
211
- describe "aasm_write_attribute helper method" do
212
- let(:sym) { :sym }
213
- let(:value) { 42 }
214
-
215
- before :each do
216
- allow(gate).to receive(:write_attribute)
217
- allow(gate).to receive(:aasm_raw_attribute_value).and_return(value)
225
+ it "generates attribute value using a helper method" do
226
+ expect(gate).to have_received(:aasm_raw_attribute_value).with(sym, :left)
227
+ end
218
228
 
219
- gate.send(:aasm_write_attribute, sym, :left)
229
+ it "writes attribute to the model" do
230
+ expect(gate).to have_received(:write_attribute).with(:aasm_state, value)
231
+ end
220
232
  end
221
233
 
222
- it "generates attribute value using a helper method" do
223
- expect(gate).to have_received(:aasm_raw_attribute_value).with(sym, :left)
234
+ it "should return the initial state when new and the aasm field is nil" do
235
+ expect(gate.aasm(:left).current_state).to eq(:opened)
224
236
  end
225
237
 
226
- it "writes attribute to the model" do
227
- expect(gate).to have_received(:write_attribute).with(:aasm_state, value)
238
+ it "should return the aasm column when new and the aasm field is not nil" do
239
+ gate.aasm_state = "closed"
240
+ expect(gate.aasm(:left).current_state).to eq(:closed)
228
241
  end
229
- end
230
242
 
231
- it "should return the initial state when new and the aasm field is nil" do
232
- expect(gate.aasm(:left).current_state).to eq(:opened)
233
- end
243
+ it "should return the aasm column when not new and the aasm.attribute_name is not nil" do
244
+ allow(gate).to receive(:new_record?).and_return(false)
245
+ gate.aasm_state = "state"
246
+ expect(gate.aasm(:left).current_state).to eq(:state)
247
+ end
234
248
 
235
- it "should return the aasm column when new and the aasm field is not nil" do
236
- gate.aasm_state = "closed"
237
- expect(gate.aasm(:left).current_state).to eq(:closed)
238
- end
249
+ it "should allow a nil state" do
250
+ allow(gate).to receive(:new_record?).and_return(false)
251
+ gate.aasm_state = nil
252
+ expect(gate.aasm(:left).current_state).to be_nil
253
+ end
239
254
 
240
- it "should return the aasm column when not new and the aasm.attribute_name is not nil" do
241
- allow(gate).to receive(:new_record?).and_return(false)
242
- gate.aasm_state = "state"
243
- expect(gate.aasm(:left).current_state).to eq(:state)
244
- end
255
+ context 'on initialization' do
256
+ it "should initialize the aasm state" do
257
+ expect(MultipleGate.new.aasm_state).to eql 'opened'
258
+ expect(MultipleGate.new.aasm(:left).current_state).to eql :opened
259
+ end
245
260
 
246
- it "should allow a nil state" do
247
- allow(gate).to receive(:new_record?).and_return(false)
248
- gate.aasm_state = nil
249
- expect(gate.aasm(:left).current_state).to be_nil
250
- end
261
+ it "should not initialize the aasm state if it has not been loaded" do
262
+ # we have to create a gate in the database, for which we only want to
263
+ # load the id, and not the state
264
+ gate = MultipleGate.create!
251
265
 
252
- context 'on initialization' do
253
- it "should initialize the aasm state" do
254
- expect(MultipleGate.new.aasm_state).to eql 'opened'
255
- expect(MultipleGate.new.aasm(:left).current_state).to eql :opened
266
+ # then we just load the gate ids
267
+ MultipleGate.select(:id).where(id: gate.id).first
268
+ end
256
269
  end
257
270
 
258
- it "should not initialize the aasm state if it has not been loaded" do
259
- # we have to create a gate in the database, for which we only want to
260
- # load the id, and not the state
261
- gate = MultipleGate.create!
271
+ end
262
272
 
263
- # then we just load the gate ids
264
- MultipleGate.select(:id).where(id: gate.id).first
273
+ if ActiveRecord::VERSION::MAJOR < 4 && ActiveRecord::VERSION::MINOR < 2 # won't work with Rails >= 4.2
274
+ describe "direct state column access" do
275
+ it "accepts false states" do
276
+ f = MultipleFalseState.create!
277
+ expect(f.aasm_state).to eql false
278
+ expect {
279
+ f.aasm(:left).events.map(&:name)
280
+ }.to_not raise_error
265
281
  end
266
282
  end
267
-
268
- end
269
-
270
- if ActiveRecord::VERSION::MAJOR < 4 && ActiveRecord::VERSION::MINOR < 2 # won't work with Rails >= 4.2
271
- describe "direct state column access" do
272
- it "accepts false states" do
273
- f = MultipleFalseState.create!
274
- expect(f.aasm_state).to eql false
275
- expect {
276
- f.aasm(:left).events.map(&:name)
277
- }.to_not raise_error
278
283
  end
279
- end
280
- end
281
284
 
282
- describe 'subclasses' do
283
- it "should have the same states as its parent class" do
284
- expect(MultipleDerivateNewDsl.aasm(:left).states).to eq(MultipleSimpleNewDsl.aasm(:left).states)
285
- end
285
+ describe 'subclasses' do
286
+ it "should have the same states as its parent class" do
287
+ expect(MultipleDerivateNewDsl.aasm(:left).states).to eq(MultipleSimpleNewDsl.aasm(:left).states)
288
+ end
286
289
 
287
- it "should have the same events as its parent class" do
288
- expect(MultipleDerivateNewDsl.aasm(:left).events).to eq(MultipleSimpleNewDsl.aasm(:left).events)
289
- end
290
+ it "should have the same events as its parent class" do
291
+ expect(MultipleDerivateNewDsl.aasm(:left).events).to eq(MultipleSimpleNewDsl.aasm(:left).events)
292
+ end
290
293
 
291
- it "should have the same column as its parent even for the new dsl" do
292
- expect(MultipleSimpleNewDsl.aasm(:left).attribute_name).to eq(:status)
293
- expect(MultipleDerivateNewDsl.aasm(:left).attribute_name).to eq(:status)
294
+ it "should have the same column as its parent even for the new dsl" do
295
+ expect(MultipleSimpleNewDsl.aasm(:left).attribute_name).to eq(:status)
296
+ expect(MultipleDerivateNewDsl.aasm(:left).attribute_name).to eq(:status)
297
+ end
294
298
  end
295
- end
296
299
 
297
- describe "named scopes with the new DSL" do
298
- context "Does not already respond_to? the scope name" do
299
- it "should add a scope for each state" do
300
- expect(MultipleSimpleNewDsl).to respond_to(:unknown_scope)
301
- expect(MultipleSimpleNewDsl).to respond_to(:another_unknown_scope)
300
+ describe "named scopes with the new DSL" do
301
+ context "Does not already respond_to? the scope name" do
302
+ it "should add a scope for each state" do
303
+ expect(MultipleSimpleNewDsl).to respond_to(:unknown_scope)
304
+ expect(MultipleSimpleNewDsl).to respond_to(:another_unknown_scope)
302
305
 
303
- expect(MultipleSimpleNewDsl.unknown_scope.is_a?(ActiveRecord::Relation)).to be_truthy
304
- expect(MultipleSimpleNewDsl.another_unknown_scope.is_a?(ActiveRecord::Relation)).to be_truthy
306
+ expect(MultipleSimpleNewDsl.unknown_scope.is_a?(ActiveRecord::Relation)).to be_truthy
307
+ expect(MultipleSimpleNewDsl.another_unknown_scope.is_a?(ActiveRecord::Relation)).to be_truthy
308
+ end
305
309
  end
306
- end
307
310
 
308
- context "Already respond_to? the scope name" do
309
- it "should not add a scope" do
310
- expect(MultipleSimpleNewDsl).to respond_to(:new)
311
- expect(MultipleSimpleNewDsl.new.class).to eq(MultipleSimpleNewDsl)
311
+ context "Already respond_to? the scope name" do
312
+ it "should not add a scope" do
313
+ expect(MultipleSimpleNewDsl).to respond_to(:new)
314
+ expect(MultipleSimpleNewDsl.new.class).to eq(MultipleSimpleNewDsl)
315
+ end
312
316
  end
313
- end
314
317
 
315
- it "does not create scopes if requested" do
316
- expect(MultipleNoScope).not_to respond_to(:pending)
317
- end
318
+ it "does not create scopes if requested" do
319
+ expect(MultipleNoScope).not_to respond_to(:pending)
320
+ end
318
321
 
319
- context "result of scope" do
320
- let!(:dsl1) { MultipleSimpleNewDsl.create!(status: :new) }
321
- let!(:dsl2) { MultipleSimpleNewDsl.create!(status: :unknown_scope) }
322
+ context "result of scope" do
323
+ let!(:dsl1) { MultipleSimpleNewDsl.create!(status: :new) }
324
+ let!(:dsl2) { MultipleSimpleNewDsl.create!(status: :unknown_scope) }
322
325
 
323
- after do
324
- MultipleSimpleNewDsl.destroy_all
325
- end
326
+ after do
327
+ MultipleSimpleNewDsl.destroy_all
328
+ end
326
329
 
327
- it "created scope works as where(name: :scope_name)" do
328
- expect(MultipleSimpleNewDsl.unknown_scope).to contain_exactly(dsl2)
330
+ it "created scope works as where(name: :scope_name)" do
331
+ expect(MultipleSimpleNewDsl.unknown_scope).to contain_exactly(dsl2)
332
+ end
329
333
  end
330
- end
331
- end # scopes
332
334
 
333
- describe "direct assignment" do
334
- it "is allowed by default" do
335
- obj = MultipleNoScope.create
336
- expect(obj.aasm_state.to_sym).to eql :pending
335
+ context "when namespeced" do
336
+ it "add namespaced scopes" do
337
+ expect(MultipleNamespaced).to respond_to(:car_unsold)
338
+ expect(MultipleNamespaced).to respond_to(:car_sold)
337
339
 
338
- obj.aasm_state = :running
339
- expect(obj.aasm_state.to_sym).to eql :running
340
- end
340
+ expect(MultipleNamespaced.car_unsold.is_a?(ActiveRecord::Relation)).to be_truthy
341
+ expect(MultipleNamespaced.car_sold.is_a?(ActiveRecord::Relation)).to be_truthy
342
+ end
343
+ it "add unnamespaced scopes" do
344
+ expect(MultipleNamespaced).to respond_to(:unsold)
345
+ expect(MultipleNamespaced).to respond_to(:sold)
341
346
 
342
- it "is forbidden if configured" do
343
- obj = MultipleNoDirectAssignment.create
344
- expect(obj.aasm_state.to_sym).to eql :pending
347
+ expect(MultipleNamespaced.unsold.is_a?(ActiveRecord::Relation)).to be_truthy
348
+ expect(MultipleNamespaced.sold.is_a?(ActiveRecord::Relation)).to be_truthy
349
+ end
350
+ end
351
+ end # scopes
345
352
 
346
- expect {obj.aasm_state = :running}.to raise_error(AASM::NoDirectAssignmentError)
347
- expect(obj.aasm_state.to_sym).to eql :pending
348
- end
353
+ describe "direct assignment" do
354
+ it "is allowed by default" do
355
+ obj = MultipleNoScope.create
356
+ expect(obj.aasm_state.to_sym).to eql :pending
349
357
 
350
- it 'can be turned off and on again' do
351
- obj = MultipleNoDirectAssignment.create
352
- expect(obj.aasm_state.to_sym).to eql :pending
358
+ obj.aasm_state = :running
359
+ expect(obj.aasm_state.to_sym).to eql :running
360
+ end
353
361
 
354
- expect {obj.aasm_state = :running}.to raise_error(AASM::NoDirectAssignmentError)
355
- expect(obj.aasm_state.to_sym).to eql :pending
362
+ it "is forbidden if configured" do
363
+ obj = MultipleNoDirectAssignment.create
364
+ expect(obj.aasm_state.to_sym).to eql :pending
356
365
 
357
- # allow it temporarily
358
- MultipleNoDirectAssignment.aasm(:left).state_machine.config.no_direct_assignment = false
359
- obj.aasm_state = :pending
360
- expect(obj.aasm_state.to_sym).to eql :pending
366
+ expect {obj.aasm_state = :running}.to raise_error(AASM::NoDirectAssignmentError)
367
+ expect(obj.aasm_state.to_sym).to eql :pending
368
+ end
361
369
 
362
- # and forbid it again
363
- MultipleNoDirectAssignment.aasm(:left).state_machine.config.no_direct_assignment = true
364
- expect {obj.aasm_state = :running}.to raise_error(AASM::NoDirectAssignmentError)
365
- expect(obj.aasm_state.to_sym).to eql :pending
366
- end
367
- end # direct assignment
370
+ it 'can be turned off and on again' do
371
+ obj = MultipleNoDirectAssignment.create
372
+ expect(obj.aasm_state.to_sym).to eql :pending
368
373
 
369
- describe 'initial states' do
370
- it 'should support conditions' do
371
- expect(MultipleThief.new(:skilled => true).aasm(:left).current_state).to eq(:rich)
372
- expect(MultipleThief.new(:skilled => false).aasm(:left).current_state).to eq(:jailed)
373
- end
374
- end
374
+ expect {obj.aasm_state = :running}.to raise_error(AASM::NoDirectAssignmentError)
375
+ expect(obj.aasm_state.to_sym).to eql :pending
375
376
 
376
- describe 'transitions with persistence' do
377
+ # allow it temporarily
378
+ MultipleNoDirectAssignment.aasm(:left).state_machine.config.no_direct_assignment = false
379
+ obj.aasm_state = :running
380
+ expect(obj.aasm_state.to_sym).to eql :running
377
381
 
378
- it "should work for valid models" do
379
- valid_object = MultipleValidator.create(:name => 'name')
380
- expect(valid_object).to be_sleeping
381
- valid_object.status = :running
382
- expect(valid_object).to be_running
383
- end
382
+ # and forbid it again
383
+ MultipleNoDirectAssignment.aasm(:left).state_machine.config.no_direct_assignment = true
384
+ expect {obj.aasm_state = :pending}.to raise_error(AASM::NoDirectAssignmentError)
385
+ expect(obj.aasm_state.to_sym).to eql :running
386
+ end
387
+ end # direct assignment
384
388
 
385
- it 'should not store states for invalid models' do
386
- validator = MultipleValidator.create(:name => 'name')
387
- expect(validator).to be_valid
388
- expect(validator).to be_sleeping
389
+ describe 'initial states' do
390
+ it 'should support conditions' do
391
+ expect(MultipleThief.new(:skilled => true).aasm(:left).current_state).to eq(:rich)
392
+ expect(MultipleThief.new(:skilled => false).aasm(:left).current_state).to eq(:jailed)
393
+ end
394
+ end
389
395
 
390
- validator.name = nil
391
- expect(validator).not_to be_valid
392
- expect { validator.run! }.to raise_error(ActiveRecord::RecordInvalid)
393
- expect(validator).to be_sleeping
396
+ describe 'transitions with persistence' do
394
397
 
395
- validator.reload
396
- expect(validator).not_to be_running
397
- expect(validator).to be_sleeping
398
+ it "should work for valid models" do
399
+ valid_object = MultipleValidator.create(:name => 'name')
400
+ expect(valid_object).to be_sleeping
401
+ valid_object.status = :running
402
+ expect(valid_object).to be_running
403
+ end
398
404
 
399
- validator.name = 'another name'
400
- expect(validator).to be_valid
401
- expect(validator.run!).to be_truthy
402
- expect(validator).to be_running
405
+ it 'should not store states for invalid models' do
406
+ validator = MultipleValidator.create(:name => 'name')
407
+ expect(validator).to be_valid
408
+ expect(validator).to be_sleeping
403
409
 
404
- validator.reload
405
- expect(validator).to be_running
406
- expect(validator).not_to be_sleeping
407
- end
410
+ validator.name = nil
411
+ expect(validator).not_to be_valid
412
+ expect { validator.run! }.to raise_error(ActiveRecord::RecordInvalid)
413
+ expect(validator).to be_sleeping
408
414
 
409
- it 'should not store states for invalid models silently if configured' do
410
- validator = MultipleSilentPersistor.create(:name => 'name')
411
- expect(validator).to be_valid
412
- expect(validator).to be_sleeping
415
+ validator.reload
416
+ expect(validator).not_to be_running
417
+ expect(validator).to be_sleeping
413
418
 
414
- validator.name = nil
415
- expect(validator).not_to be_valid
416
- expect(validator.run!).to be_falsey
417
- expect(validator).to be_sleeping
419
+ validator.name = 'another name'
420
+ expect(validator).to be_valid
421
+ expect(validator.run!).to be_truthy
422
+ expect(validator).to be_running
418
423
 
419
- validator.reload
420
- expect(validator).not_to be_running
421
- expect(validator).to be_sleeping
424
+ validator.reload
425
+ expect(validator).to be_running
426
+ expect(validator).not_to be_sleeping
427
+ end
422
428
 
423
- validator.name = 'another name'
424
- expect(validator).to be_valid
425
- expect(validator.run!).to be_truthy
426
- expect(validator).to be_running
429
+ it 'should not store states for invalid models silently if configured' do
430
+ validator = MultipleSilentPersistor.create(:name => 'name')
431
+ expect(validator).to be_valid
432
+ expect(validator).to be_sleeping
427
433
 
428
- validator.reload
429
- expect(validator).to be_running
430
- expect(validator).not_to be_sleeping
431
- end
434
+ validator.name = nil
435
+ expect(validator).not_to be_valid
436
+ expect(validator.run!).to be_falsey
437
+ expect(validator).to be_sleeping
432
438
 
433
- it 'should store states for invalid models if configured' do
434
- persistor = MultipleInvalidPersistor.create(:name => 'name')
435
- expect(persistor).to be_valid
436
- expect(persistor).to be_sleeping
437
-
438
- persistor.name = nil
439
- expect(persistor).not_to be_valid
440
- expect(persistor.run!).to be_truthy
441
- expect(persistor).to be_running
442
-
443
- persistor = MultipleInvalidPersistor.find(persistor.id)
444
- persistor.valid?
445
- expect(persistor).to be_valid
446
- expect(persistor).to be_running
447
- expect(persistor).not_to be_sleeping
448
-
449
- persistor.reload
450
- expect(persistor).to be_running
451
- expect(persistor).not_to be_sleeping
452
- end
439
+ validator.reload
440
+ expect(validator).not_to be_running
441
+ expect(validator).to be_sleeping
453
442
 
454
- describe 'transactions' do
455
- let(:worker) { Worker.create!(:name => 'worker', :status => 'sleeping') }
456
- let(:transactor) { MultipleTransactor.create!(:name => 'transactor', :worker => worker) }
443
+ validator.name = 'another name'
444
+ expect(validator).to be_valid
445
+ expect(validator.run!).to be_truthy
446
+ expect(validator).to be_running
457
447
 
458
- it 'should rollback all changes' do
459
- expect(transactor).to be_sleeping
460
- expect(worker.status).to eq('sleeping')
448
+ validator.reload
449
+ expect(validator).to be_running
450
+ expect(validator).not_to be_sleeping
451
+ end
461
452
 
462
- expect {transactor.run!}.to raise_error(StandardError, 'failed on purpose')
463
- expect(transactor).to be_running
464
- expect(worker.reload.status).to eq('sleeping')
453
+ it 'should store states for invalid models if configured' do
454
+ persistor = MultipleInvalidPersistor.create(:name => 'name')
455
+ expect(persistor).to be_valid
456
+ expect(persistor).to be_sleeping
457
+
458
+ persistor.name = nil
459
+ expect(persistor).not_to be_valid
460
+ expect(persistor.run!).to be_truthy
461
+ expect(persistor).to be_running
462
+
463
+ persistor = MultipleInvalidPersistor.find(persistor.id)
464
+ persistor.valid?
465
+ expect(persistor).to be_valid
466
+ expect(persistor).to be_running
467
+ expect(persistor).not_to be_sleeping
468
+
469
+ persistor.reload
470
+ expect(persistor).to be_running
471
+ expect(persistor).not_to be_sleeping
465
472
  end
466
473
 
467
- context "nested transactions" do
468
- it "should rollback all changes in nested transaction" do
474
+ describe 'transactions' do
475
+ let(:worker) { Worker.create!(:name => 'worker', :status => 'sleeping') }
476
+ let(:transactor) { MultipleTransactor.create!(:name => 'transactor', :worker => worker) }
477
+
478
+ it 'should rollback all changes' do
469
479
  expect(transactor).to be_sleeping
470
480
  expect(worker.status).to eq('sleeping')
471
481
 
472
- Worker.transaction do
473
- expect { transactor.run! }.to raise_error(StandardError, 'failed on purpose')
474
- end
475
-
482
+ expect {transactor.run!}.to raise_error(StandardError, 'failed on purpose')
476
483
  expect(transactor).to be_running
477
484
  expect(worker.reload.status).to eq('sleeping')
478
485
  end
479
486
 
480
- it "should only rollback changes in the main transaction not the nested one" do
481
- # change configuration to not require new transaction
482
- AASM::StateMachineStore[MultipleTransactor][:left].config.requires_new_transaction = false
487
+ context "nested transactions" do
488
+ it "should rollback all changes in nested transaction" do
489
+ expect(transactor).to be_sleeping
490
+ expect(worker.status).to eq('sleeping')
483
491
 
484
- expect(transactor).to be_sleeping
485
- expect(worker.status).to eq('sleeping')
492
+ Worker.transaction do
493
+ expect { transactor.run! }.to raise_error(StandardError, 'failed on purpose')
494
+ end
486
495
 
487
- Worker.transaction do
488
- expect { transactor.run! }.to raise_error(StandardError, 'failed on purpose')
496
+ expect(transactor).to be_running
497
+ expect(worker.reload.status).to eq('sleeping')
489
498
  end
490
499
 
491
- expect(transactor).to be_running
492
- expect(worker.reload.status).to eq('running')
493
- end
494
- end
500
+ it "should only rollback changes in the main transaction not the nested one" do
501
+ # change configuration to not require new transaction
502
+ AASM::StateMachineStore[MultipleTransactor][:left].config.requires_new_transaction = false
495
503
 
496
- describe "after_commit callback" do
497
- it "should fire :after_commit if transaction was successful" do
498
- validator = MultipleValidator.create(:name => 'name')
499
- expect(validator).to be_sleeping
504
+ expect(transactor).to be_sleeping
505
+ expect(worker.status).to eq('sleeping')
500
506
 
501
- validator.run!
502
- expect(validator).to be_running
503
- expect(validator.name).to eq("name changed")
507
+ Worker.transaction do
508
+ expect { transactor.run! }.to raise_error(StandardError, 'failed on purpose')
509
+ end
504
510
 
505
- validator.sleep!("sleeper")
506
- expect(validator).to be_sleeping
507
- expect(validator.name).to eq("sleeper")
511
+ expect(transactor).to be_running
512
+ expect(worker.reload.status).to eq('running')
513
+ end
508
514
  end
509
515
 
510
- it "should not fire :after_commit if transaction failed" do
511
- validator = MultipleValidator.create(:name => 'name')
512
- expect { validator.fail! }.to raise_error(StandardError, 'failed on purpose')
513
- expect(validator.name).to eq("name")
514
- end
516
+ describe "after_commit callback" do
517
+ it "should fire :after_commit if transaction was successful" do
518
+ validator = MultipleValidator.create(:name => 'name')
519
+ expect(validator).to be_sleeping
515
520
 
516
- it "should not fire if not saving" do
517
- validator = MultipleValidator.create(:name => 'name')
518
- expect(validator).to be_sleeping
519
- validator.run
520
- expect(validator).to be_running
521
- expect(validator.name).to eq("name")
522
- end
521
+ validator.run!
522
+ expect(validator).to be_running
523
+ expect(validator.name).to eq("name changed")
523
524
 
524
- end
525
+ validator.sleep!("sleeper")
526
+ expect(validator).to be_sleeping
527
+ expect(validator.name).to eq("sleeper")
528
+ end
525
529
 
526
- context "when not persisting" do
527
- it 'should not rollback all changes' do
528
- expect(transactor).to be_sleeping
529
- expect(worker.status).to eq('sleeping')
530
+ it "should not fire :after_commit if transaction failed" do
531
+ validator = MultipleValidator.create(:name => 'name')
532
+ expect { validator.fail! }.to raise_error(StandardError, 'failed on purpose')
533
+ expect(validator.name).to eq("name")
534
+ end
535
+
536
+ it "should not fire if not saving" do
537
+ validator = MultipleValidator.create(:name => 'name')
538
+ expect(validator).to be_sleeping
539
+ validator.run
540
+ expect(validator).to be_running
541
+ expect(validator.name).to eq("name")
542
+ end
530
543
 
531
- # Notice here we're calling "run" and not "run!" with a bang.
532
- expect {transactor.run}.to raise_error(StandardError, 'failed on purpose')
533
- expect(transactor).to be_running
534
- expect(worker.reload.status).to eq('running')
535
544
  end
536
545
 
537
- it 'should not create a database transaction' do
538
- expect(transactor.class).not_to receive(:transaction)
539
- expect {transactor.run}.to raise_error(StandardError, 'failed on purpose')
546
+ context "when not persisting" do
547
+ it 'should not rollback all changes' do
548
+ expect(transactor).to be_sleeping
549
+ expect(worker.status).to eq('sleeping')
550
+
551
+ # Notice here we're calling "run" and not "run!" with a bang.
552
+ expect {transactor.run}.to raise_error(StandardError, 'failed on purpose')
553
+ expect(transactor).to be_running
554
+ expect(worker.reload.status).to eq('running')
555
+ end
556
+
557
+ it 'should not create a database transaction' do
558
+ expect(transactor.class).not_to receive(:transaction)
559
+ expect {transactor.run}.to raise_error(StandardError, 'failed on purpose')
560
+ end
540
561
  end
541
562
  end
542
563
  end
543
- end
544
564
 
545
- describe "invalid states with persistence" do
546
- it "should not store states" do
547
- validator = MultipleValidator.create(:name => 'name')
548
- validator.status = 'invalid_state'
549
- expect(validator.save).to be_falsey
550
- expect {validator.save!}.to raise_error(ActiveRecord::RecordInvalid)
565
+ describe "invalid states with persistence" do
566
+ it "should not store states" do
567
+ validator = MultipleValidator.create(:name => 'name')
568
+ validator.status = 'invalid_state'
569
+ expect(validator.save).to be_falsey
570
+ expect {validator.save!}.to raise_error(ActiveRecord::RecordInvalid)
551
571
 
552
- validator.reload
553
- expect(validator).to be_sleeping
554
- end
572
+ validator.reload
573
+ expect(validator).to be_sleeping
574
+ end
555
575
 
556
- it "should store invalid states if configured" do
557
- persistor = MultipleInvalidPersistor.create(:name => 'name')
558
- persistor.status = 'invalid_state'
559
- expect(persistor.save).to be_truthy
576
+ it "should store invalid states if configured" do
577
+ persistor = MultipleInvalidPersistor.create(:name => 'name')
578
+ persistor.status = 'invalid_state'
579
+ expect(persistor.save).to be_truthy
560
580
 
561
- persistor.reload
562
- expect(persistor.status).to eq('invalid_state')
581
+ persistor.reload
582
+ expect(persistor.status).to eq('invalid_state')
583
+ end
563
584
  end
564
- end
565
585
 
566
- describe "complex example" do
567
- it "works" do
568
- record = ComplexActiveRecordExample.new
569
- expect_aasm_states record, :one, :alpha
570
-
571
- record.save!
572
- expect_aasm_states record, :one, :alpha
573
- record.reload
574
- expect_aasm_states record, :one, :alpha
575
-
576
- record.increment!
577
- expect_aasm_states record, :two, :alpha
578
- record.reload
579
- expect_aasm_states record, :two, :alpha
580
-
581
- record.level_up!
582
- expect_aasm_states record, :two, :beta
583
- record.reload
584
- expect_aasm_states record, :two, :beta
585
-
586
- record.increment!
587
- expect { record.increment! }.to raise_error(AASM::InvalidTransition)
588
- expect_aasm_states record, :three, :beta
589
- record.reload
590
- expect_aasm_states record, :three, :beta
591
-
592
- record.level_up!
593
- expect_aasm_states record, :three, :gamma
594
- record.reload
595
- expect_aasm_states record, :three, :gamma
596
-
597
- record.level_down # without saving
598
- expect_aasm_states record, :three, :beta
599
- record.reload
600
- expect_aasm_states record, :three, :gamma
601
-
602
- record.level_down # without saving
603
- expect_aasm_states record, :three, :beta
604
- record.reset!
605
- expect_aasm_states record, :one, :beta
606
- end
586
+ describe "complex example" do
587
+ it "works" do
588
+ record = ComplexActiveRecordExample.new
589
+ expect_aasm_states record, :one, :alpha
590
+
591
+ record.save!
592
+ expect_aasm_states record, :one, :alpha
593
+ record.reload
594
+ expect_aasm_states record, :one, :alpha
595
+
596
+ record.increment!
597
+ expect_aasm_states record, :two, :alpha
598
+ record.reload
599
+ expect_aasm_states record, :two, :alpha
600
+
601
+ record.level_up!
602
+ expect_aasm_states record, :two, :beta
603
+ record.reload
604
+ expect_aasm_states record, :two, :beta
605
+
606
+ record.increment!
607
+ expect { record.increment! }.to raise_error(AASM::InvalidTransition)
608
+ expect_aasm_states record, :three, :beta
609
+ record.reload
610
+ expect_aasm_states record, :three, :beta
611
+
612
+ record.level_up!
613
+ expect_aasm_states record, :three, :gamma
614
+ record.reload
615
+ expect_aasm_states record, :three, :gamma
616
+
617
+ record.level_down # without saving
618
+ expect_aasm_states record, :three, :beta
619
+ record.reload
620
+ expect_aasm_states record, :three, :gamma
621
+
622
+ record.level_down # without saving
623
+ expect_aasm_states record, :three, :beta
624
+ record.reset!
625
+ expect_aasm_states record, :one, :beta
626
+ end
607
627
 
608
- def expect_aasm_states(record, left_state, right_state)
609
- expect(record.aasm(:left).current_state).to eql left_state.to_sym
610
- expect(record.left).to eql left_state.to_s
611
- expect(record.aasm(:right).current_state).to eql right_state.to_sym
612
- expect(record.right).to eql right_state.to_s
628
+ def expect_aasm_states(record, left_state, right_state)
629
+ expect(record.aasm(:left).current_state).to eql left_state.to_sym
630
+ expect(record.left).to eql left_state.to_s
631
+ expect(record.aasm(:right).current_state).to eql right_state.to_sym
632
+ expect(record.right).to eql right_state.to_s
633
+ end
613
634
  end
614
635
  end