aasm 5.0.6 → 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 (55) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +13 -13
  3. data/Appraisals +6 -10
  4. data/CHANGELOG.md +33 -0
  5. data/Gemfile +1 -1
  6. data/README.md +102 -13
  7. data/aasm.gemspec +1 -1
  8. data/gemfiles/norails.gemfile +1 -1
  9. data/gemfiles/rails_4.2.gemfile +1 -0
  10. data/gemfiles/rails_4.2_mongoid_5.gemfile +1 -0
  11. data/gemfiles/rails_5.0.gemfile +1 -0
  12. data/gemfiles/rails_5.1.gemfile +1 -0
  13. data/gemfiles/rails_5.2.gemfile +1 -0
  14. data/lib/aasm.rb +0 -2
  15. data/lib/aasm/base.rb +30 -11
  16. data/lib/aasm/configuration.rb +3 -0
  17. data/lib/aasm/core/event.rb +7 -2
  18. data/lib/aasm/core/state.rb +6 -5
  19. data/lib/aasm/core/transition.rb +1 -1
  20. data/lib/aasm/dsl_helper.rb +24 -22
  21. data/lib/aasm/instance_base.rb +12 -1
  22. data/lib/aasm/localizer.rb +13 -3
  23. data/lib/aasm/persistence/active_record_persistence.rb +18 -0
  24. data/lib/aasm/persistence/base.rb +13 -2
  25. data/lib/aasm/persistence/orm.rb +23 -19
  26. data/lib/aasm/rspec/transition_from.rb +5 -1
  27. data/lib/aasm/version.rb +1 -1
  28. data/spec/database.rb +10 -12
  29. data/spec/en.yml +0 -3
  30. data/spec/{en_deprecated_style.yml → localizer_test_model_deprecated_style.yml} +6 -3
  31. data/spec/localizer_test_model_new_style.yml +11 -0
  32. data/spec/models/active_record/active_record_callback.rb +93 -0
  33. data/spec/models/active_record/localizer_test_model.rb +11 -3
  34. data/spec/models/active_record/namespaced.rb +16 -0
  35. data/spec/models/active_record/timestamp_example.rb +16 -0
  36. data/spec/models/default_state.rb +1 -1
  37. data/spec/models/mongoid/timestamp_example_mongoid.rb +20 -0
  38. data/spec/models/simple_example.rb +6 -0
  39. data/spec/models/timestamps_example.rb +19 -0
  40. data/spec/models/timestamps_with_named_machine_example.rb +13 -0
  41. data/spec/spec_helper.rb +5 -0
  42. data/spec/unit/api_spec.rb +4 -0
  43. data/spec/unit/inspection_multiple_spec.rb +9 -5
  44. data/spec/unit/inspection_spec.rb +7 -3
  45. data/spec/unit/localizer_spec.rb +49 -18
  46. data/spec/unit/persistence/active_record_persistence_multiple_spec.rb +17 -0
  47. data/spec/unit/persistence/active_record_persistence_spec.rb +79 -0
  48. data/spec/unit/persistence/mongoid_persistence_spec.rb +12 -0
  49. data/spec/unit/rspec_matcher_spec.rb +3 -0
  50. data/spec/unit/simple_example_spec.rb +15 -0
  51. data/spec/unit/state_spec.rb +21 -5
  52. data/spec/unit/timestamps_spec.rb +32 -0
  53. metadata +26 -13
  54. data/callbacks.txt +0 -51
  55. data/gemfiles/rails_3.2.gemfile +0 -14
@@ -331,6 +331,23 @@ if defined?(ActiveRecord)
331
331
  expect(MultipleSimpleNewDsl.unknown_scope).to contain_exactly(dsl2)
332
332
  end
333
333
  end
334
+
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)
339
+
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)
346
+
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
334
351
  end # scopes
335
352
 
336
353
  describe "direct assignment" do
@@ -613,6 +613,73 @@ if defined?(ActiveRecord)
613
613
  expect(validator).to be_running
614
614
  expect(validator.name).to eq("name")
615
615
  end
616
+
617
+ context "nested transaction" do
618
+ it "should fire :after_commit if root transaction was successful" do
619
+ validator = Validator.create(:name => 'name')
620
+ expect(validator).to be_sleeping
621
+
622
+ validator.transaction do
623
+ validator.run!
624
+ expect(validator.name).to eq("name")
625
+ expect(validator).to be_running
626
+ end
627
+
628
+ expect(validator.name).to eq("name changed")
629
+ expect(validator.reload).to be_running
630
+ end
631
+
632
+ it "should not fire :after_commit if root transaction failed" do
633
+ validator = Validator.create(:name => 'name')
634
+ expect(validator).to be_sleeping
635
+
636
+ validator.transaction do
637
+ validator.run!
638
+ expect(validator.name).to eq("name")
639
+ expect(validator).to be_running
640
+
641
+ raise ActiveRecord::Rollback, "failed on purpose"
642
+ end
643
+
644
+ expect(validator.name).to eq("name")
645
+ expect(validator.reload).to be_sleeping
646
+ end
647
+ end
648
+ end
649
+
650
+ describe 'callbacks for the new DSL' do
651
+
652
+ it "be called in order" do
653
+ show_debug_log = false
654
+
655
+ callback = ActiveRecordCallback.create
656
+ callback.aasm.current_state
657
+
658
+ unless show_debug_log
659
+ expect(callback).to receive(:before_all_events).once.ordered
660
+ expect(callback).to receive(:before_event).once.ordered
661
+ expect(callback).to receive(:event_guard).once.ordered.and_return(true)
662
+ expect(callback).to receive(:transition_guard).once.ordered.and_return(true)
663
+ expect(callback).to receive(:before_exit_open).once.ordered # these should be before the state changes
664
+ expect(callback).to receive(:exit_open).once.ordered
665
+ # expect(callback).to receive(:event_guard).once.ordered.and_return(true)
666
+ # expect(callback).to receive(:transition_guard).once.ordered.and_return(true)
667
+ expect(callback).to receive(:after_all_transitions).once.ordered
668
+ expect(callback).to receive(:after_transition).once.ordered
669
+ expect(callback).to receive(:before_enter_closed).once.ordered
670
+ expect(callback).to receive(:enter_closed).once.ordered
671
+ expect(callback).to receive(:aasm_write_state).once.ordered.and_return(true) # this is when the state changes
672
+ expect(callback).to receive(:after_exit_open).once.ordered # these should be after the state changes
673
+ expect(callback).to receive(:after_enter_closed).once.ordered
674
+ expect(callback).to receive(:after_event).once.ordered
675
+ expect(callback).to receive(:after_all_events).once.ordered
676
+ expect(callback).to receive(:ensure_event).once.ordered
677
+ expect(callback).to receive(:ensure_on_all_events).once.ordered
678
+ expect(callback).to receive(:event_after_commit).once.ordered
679
+ end
680
+
681
+ callback.close!
682
+ end
616
683
  end
617
684
 
618
685
  describe 'before and after transaction callbacks' do
@@ -770,4 +837,16 @@ if defined?(ActiveRecord)
770
837
  expect(example.complete!).to be_falsey
771
838
  end
772
839
  end
840
+
841
+ describe 'testing the timestamps option' do
842
+ let(:example) { TimestampExample.create! }
843
+
844
+ it 'should update existing timestamp columns' do
845
+ expect { example.open! }.to change { example.reload.opened_at }.from(nil).to(instance_of(::Time))
846
+ end
847
+
848
+ it 'should not fail if there is no corresponding timestamp column' do
849
+ expect { example.close! }.to change { example.reload.aasm_state }
850
+ end
851
+ end
773
852
  end
@@ -161,5 +161,17 @@ if defined?(Mongoid::Document)
161
161
  end
162
162
  end
163
163
 
164
+ describe 'testing the timestamps option' do
165
+ let(:example) { TimestampExampleMongoid.create }
166
+
167
+ it 'should update existing timestamp fields' do
168
+ expect { example.open! }.to change { example.reload.opened_at }.from(nil).to(instance_of(::Time))
169
+ end
170
+
171
+ it 'should not fail if there is no corresponding timestamp field' do
172
+ expect { example.close! }.to change { example.reload.status }
173
+ end
174
+ end
175
+
164
176
  end
165
177
  end
@@ -8,14 +8,17 @@ describe 'state machine' do
8
8
  it "works for simple state machines" do
9
9
  expect(simple).to transition_from(:initialised).to(:filled_out).on_event(:fill_out)
10
10
  expect(simple).to_not transition_from(:initialised).to(:authorised).on_event(:fill_out)
11
+ expect(simple).to_not transition_from(:authorised).to(:filled_out).on_event(:fill_out)
11
12
  end
12
13
 
13
14
  it "works for multiple state machines" do
14
15
  expect(multiple).to transition_from(:standing).to(:walking).on_event(:walk).on(:move)
15
16
  expect(multiple).to_not transition_from(:standing).to(:running).on_event(:walk).on(:move)
17
+ expect(multiple).to_not transition_from(:running).to(:walking).on_event(:walk).on(:move)
16
18
 
17
19
  expect(multiple).to transition_from(:sleeping).to(:processing).on_event(:start).on(:work)
18
20
  expect(multiple).to_not transition_from(:sleeping).to(:sleeping).on_event(:start).on(:work)
21
+ expect(multiple).to_not transition_from(:processing).to(:sleeping).on_event(:start).on(:work)
19
22
  end
20
23
  end
21
24
 
@@ -23,6 +23,21 @@ describe 'state machine' do
23
23
  expect(simple).to be_authorised
24
24
  end
25
25
 
26
+ it 'shows the permitted transitions' do
27
+ expect(simple.aasm.permitted_transitions).to eq(
28
+ [
29
+ { event: :fill_out, state: :filled_out },
30
+ { event: :deny, state: :denied }
31
+ ]
32
+ )
33
+
34
+ simple.fill_out!
35
+ expect(simple.aasm.permitted_transitions).to eq([{ event: :authorise, state: :authorised }])
36
+
37
+ simple.authorise
38
+ expect(simple.aasm.permitted_transitions).to eq([])
39
+ end
40
+
26
41
  it 'denies transitions to other states' do
27
42
  expect {simple.authorise}.to raise_error(AASM::InvalidTransition)
28
43
  expect {simple.authorise!}.to raise_error(AASM::InvalidTransition)
@@ -17,12 +17,28 @@ describe AASM::Core::State do
17
17
  expect(state.name).to eq(:astate)
18
18
  end
19
19
 
20
- it 'should set the display_name from name' do
21
- expect(new_state.display_name).to eq('Astate')
22
- end
20
+ describe '#display_name' do
21
+ subject(:display_name) { new_state(options).display_name }
22
+
23
+ context 'without options' do
24
+ let(:options) { {} }
25
+
26
+ context 'without I18n' do
27
+ before { allow(Module).to receive(:const_defined?).with(:I18n).and_return(nil) }
28
+
29
+ it 'should set the display_name from name' do
30
+ expect(display_name).to eq('Astate')
31
+ end
32
+ end
33
+ end
34
+
35
+ context 'with :display option' do
36
+ let(:options) { { display: "A State" } }
23
37
 
24
- it 'should set the display_name from options' do
25
- expect(new_state(:display => "A State").display_name).to eq('A State')
38
+ it 'should set the display_name from options' do
39
+ expect(display_name).to eq('A State')
40
+ end
41
+ end
26
42
  end
27
43
 
28
44
  it 'should set the options and expose them as options' do
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'timestamps option' do
4
+ it 'calls a timestamp setter based on the state name when entering a new state' do
5
+ object = TimestampsExample.new
6
+ expect { object.open }.to change { object.opened_at }.from(nil).to(instance_of(::Time))
7
+ end
8
+
9
+ it 'overwrites any previous timestamp if a state is entered repeatedly' do
10
+ object = TimestampsExample.new
11
+ object.opened_at = ::Time.new(2000, 1, 1)
12
+ expect { object.open }.to change { object.opened_at }
13
+ end
14
+
15
+ it 'does nothing if there is no setter matching the new state' do
16
+ object = TimestampsExample.new
17
+ expect { object.close }.not_to change { object.closed_at }
18
+ end
19
+
20
+ it 'can be turned off and on' do
21
+ object = TimestampsExample.new
22
+ object.class.aasm.state_machine.config.timestamps = false
23
+ expect { object.open }.not_to change { object.opened_at }
24
+ object.class.aasm.state_machine.config.timestamps = true
25
+ expect { object.open }.to change { object.opened_at }
26
+ end
27
+
28
+ it 'calls a timestamp setter when using a named state machine' do
29
+ object = TimestampsWithNamedMachineExample.new
30
+ expect { object.open }.to change { object.opened_at }.from(nil).to(instance_of(::Time))
31
+ end
32
+ end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aasm
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.6
4
+ version: 5.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thorsten Boettger
8
8
  - Anil Maurya
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2019-09-04 00:00:00.000000000 Z
12
+ date: 2021-05-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: concurrent-ruby
@@ -115,14 +115,14 @@ dependencies:
115
115
  requirements:
116
116
  - - ">="
117
117
  - !ruby/object:Gem::Version
118
- version: 0.1.10
118
+ version: 0.1.21
119
119
  type: :development
120
120
  prerelease: false
121
121
  version_requirements: !ruby/object:Gem::Requirement
122
122
  requirements:
123
123
  - - ">="
124
124
  - !ruby/object:Gem::Version
125
- version: 0.1.10
125
+ version: 0.1.21
126
126
  - !ruby/object:Gem::Dependency
127
127
  name: pry
128
128
  requirement: !ruby/object:Gem::Requirement
@@ -165,10 +165,8 @@ files:
165
165
  - Rakefile
166
166
  - TESTING.md
167
167
  - aasm.gemspec
168
- - callbacks.txt
169
168
  - docker-compose.yml
170
169
  - gemfiles/norails.gemfile
171
- - gemfiles/rails_3.2.gemfile
172
170
  - gemfiles/rails_4.2.gemfile
173
171
  - gemfiles/rails_4.2_mongoid_5.gemfile
174
172
  - gemfiles/rails_4.2_nobrainer.gemfile
@@ -228,10 +226,12 @@ files:
228
226
  - spec/database.rb
229
227
  - spec/database.yml
230
228
  - spec/en.yml
231
- - spec/en_deprecated_style.yml
232
229
  - spec/generators/active_record_generator_spec.rb
233
230
  - spec/generators/mongoid_generator_spec.rb
234
231
  - spec/generators/no_brainer_generator_spec.rb
232
+ - spec/localizer_test_model_deprecated_style.yml
233
+ - spec/localizer_test_model_new_style.yml
234
+ - spec/models/active_record/active_record_callback.rb
235
235
  - spec/models/active_record/basic_active_record_two_state_machines_example.rb
236
236
  - spec/models/active_record/complex_active_record_example.rb
237
237
  - spec/models/active_record/derivate_new_dsl.rb
@@ -240,6 +240,7 @@ files:
240
240
  - spec/models/active_record/instance_level_skip_validation_example.rb
241
241
  - spec/models/active_record/invalid_persistor.rb
242
242
  - spec/models/active_record/localizer_test_model.rb
243
+ - spec/models/active_record/namespaced.rb
243
244
  - spec/models/active_record/no_direct_assignment.rb
244
245
  - spec/models/active_record/no_scope.rb
245
246
  - spec/models/active_record/persisted_state.rb
@@ -250,6 +251,7 @@ files:
250
251
  - spec/models/active_record/silent_persistor.rb
251
252
  - spec/models/active_record/simple_new_dsl.rb
252
253
  - spec/models/active_record/thief.rb
254
+ - spec/models/active_record/timestamp_example.rb
253
255
  - spec/models/active_record/transactor.rb
254
256
  - spec/models/active_record/transient.rb
255
257
  - spec/models/active_record/validator.rb
@@ -296,6 +298,7 @@ files:
296
298
  - spec/models/mongoid/silent_persistor_mongoid.rb
297
299
  - spec/models/mongoid/simple_mongoid.rb
298
300
  - spec/models/mongoid/simple_new_dsl_mongoid.rb
301
+ - spec/models/mongoid/timestamp_example_mongoid.rb
299
302
  - spec/models/mongoid/validator_mongoid.rb
300
303
  - spec/models/multi_transitioner.rb
301
304
  - spec/models/multiple_transitions_that_differ_only_by_guard.rb
@@ -337,6 +340,8 @@ files:
337
340
  - spec/models/sub_classing.rb
338
341
  - spec/models/super_class.rb
339
342
  - spec/models/this_name_better_not_be_in_use.rb
343
+ - spec/models/timestamps_example.rb
344
+ - spec/models/timestamps_with_named_machine_example.rb
340
345
  - spec/models/valid_state_name.rb
341
346
  - spec/spec_helper.rb
342
347
  - spec/spec_helpers/active_record.rb
@@ -401,6 +406,7 @@ files:
401
406
  - spec/unit/states_on_one_line_example_spec.rb
402
407
  - spec/unit/subclassing_multiple_spec.rb
403
408
  - spec/unit/subclassing_spec.rb
409
+ - spec/unit/timestamps_spec.rb
404
410
  - spec/unit/transition_spec.rb
405
411
  - test/minitest_helper.rb
406
412
  - test/unit/minitest_matcher_test.rb
@@ -408,7 +414,7 @@ homepage: https://github.com/aasm/aasm
408
414
  licenses:
409
415
  - MIT
410
416
  metadata: {}
411
- post_install_message:
417
+ post_install_message:
412
418
  rdoc_options: []
413
419
  require_paths:
414
420
  - lib
@@ -423,19 +429,20 @@ required_rubygems_version: !ruby/object:Gem::Requirement
423
429
  - !ruby/object:Gem::Version
424
430
  version: '0'
425
431
  requirements: []
426
- rubyforge_project:
427
- rubygems_version: 2.6.14
428
- signing_key:
432
+ rubygems_version: 3.0.3
433
+ signing_key:
429
434
  specification_version: 4
430
435
  summary: State machine mixin for Ruby objects
431
436
  test_files:
432
437
  - spec/database.rb
433
438
  - spec/database.yml
434
439
  - spec/en.yml
435
- - spec/en_deprecated_style.yml
436
440
  - spec/generators/active_record_generator_spec.rb
437
441
  - spec/generators/mongoid_generator_spec.rb
438
442
  - spec/generators/no_brainer_generator_spec.rb
443
+ - spec/localizer_test_model_deprecated_style.yml
444
+ - spec/localizer_test_model_new_style.yml
445
+ - spec/models/active_record/active_record_callback.rb
439
446
  - spec/models/active_record/basic_active_record_two_state_machines_example.rb
440
447
  - spec/models/active_record/complex_active_record_example.rb
441
448
  - spec/models/active_record/derivate_new_dsl.rb
@@ -444,6 +451,7 @@ test_files:
444
451
  - spec/models/active_record/instance_level_skip_validation_example.rb
445
452
  - spec/models/active_record/invalid_persistor.rb
446
453
  - spec/models/active_record/localizer_test_model.rb
454
+ - spec/models/active_record/namespaced.rb
447
455
  - spec/models/active_record/no_direct_assignment.rb
448
456
  - spec/models/active_record/no_scope.rb
449
457
  - spec/models/active_record/persisted_state.rb
@@ -454,6 +462,7 @@ test_files:
454
462
  - spec/models/active_record/silent_persistor.rb
455
463
  - spec/models/active_record/simple_new_dsl.rb
456
464
  - spec/models/active_record/thief.rb
465
+ - spec/models/active_record/timestamp_example.rb
457
466
  - spec/models/active_record/transactor.rb
458
467
  - spec/models/active_record/transient.rb
459
468
  - spec/models/active_record/validator.rb
@@ -500,6 +509,7 @@ test_files:
500
509
  - spec/models/mongoid/silent_persistor_mongoid.rb
501
510
  - spec/models/mongoid/simple_mongoid.rb
502
511
  - spec/models/mongoid/simple_new_dsl_mongoid.rb
512
+ - spec/models/mongoid/timestamp_example_mongoid.rb
503
513
  - spec/models/mongoid/validator_mongoid.rb
504
514
  - spec/models/multi_transitioner.rb
505
515
  - spec/models/multiple_transitions_that_differ_only_by_guard.rb
@@ -541,6 +551,8 @@ test_files:
541
551
  - spec/models/sub_classing.rb
542
552
  - spec/models/super_class.rb
543
553
  - spec/models/this_name_better_not_be_in_use.rb
554
+ - spec/models/timestamps_example.rb
555
+ - spec/models/timestamps_with_named_machine_example.rb
544
556
  - spec/models/valid_state_name.rb
545
557
  - spec/spec_helper.rb
546
558
  - spec/spec_helpers/active_record.rb
@@ -605,6 +617,7 @@ test_files:
605
617
  - spec/unit/states_on_one_line_example_spec.rb
606
618
  - spec/unit/subclassing_multiple_spec.rb
607
619
  - spec/unit/subclassing_spec.rb
620
+ - spec/unit/timestamps_spec.rb
608
621
  - spec/unit/transition_spec.rb
609
622
  - test/minitest_helper.rb
610
623
  - test/unit/minitest_matcher_test.rb
data/callbacks.txt DELETED
@@ -1,51 +0,0 @@
1
- callbacks
2
-
3
- AASM 3
4
-
5
- begin
6
- old_state exit # old? should be deprecated -> use old_state.before_exit instead
7
- event before
8
- old_state before_exit
9
- new_state before_enter
10
- new_state enter # old? should be deprecated -> use new_state.before_enter instead
11
- ...update state...
12
- transition guard
13
- event guard
14
- transition on_transition
15
- event success # if persist successful
16
- old_state after_exit
17
- new_state after_enter
18
- event after
19
- rescue
20
- event error
21
- end
22
-
23
- AASM 4
24
-
25
- todo
26
-
27
- done
28
- - move event.before before everything else
29
- - move old_state.before_exit before old_state.exit
30
- - move event.guard before transition.guard
31
- - fire guards before running state callbacks (test run)
32
-
33
- begin
34
- event before
35
- event guard # test run
36
- transition guard # test run
37
- old_state before_exit
38
- old_state exit
39
- new_state before_enter
40
- new_state enter
41
- event guard
42
- transition guard
43
- transition on_transition
44
- ...update state...
45
- event success # if persist successful
46
- old_state after_exit
47
- new_state after_enter
48
- event after
49
- rescue
50
- event error
51
- end