aasm 5.0.3 → 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 (42) 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 +42 -11
  5. data/Appraisals +17 -2
  6. data/CHANGELOG.md +33 -0
  7. data/Dockerfile +1 -6
  8. data/README.md +28 -9
  9. data/aasm.gemspec +2 -0
  10. data/gemfiles/norails.gemfile +10 -0
  11. data/gemfiles/rails_5.0.gemfile +1 -1
  12. data/gemfiles/rails_5.1.gemfile +1 -1
  13. data/gemfiles/rails_5.2.gemfile +13 -0
  14. data/lib/aasm/aasm.rb +29 -27
  15. data/lib/aasm/base.rb +25 -15
  16. data/lib/aasm/core/event.rb +3 -3
  17. data/lib/aasm/instance_base.rb +15 -3
  18. data/lib/aasm/persistence/active_record_persistence.rb +2 -1
  19. data/lib/aasm/persistence/base.rb +1 -1
  20. data/lib/aasm/persistence/core_data_query_persistence.rb +2 -1
  21. data/lib/aasm/persistence/dynamoid_persistence.rb +1 -1
  22. data/lib/aasm/persistence/mongoid_persistence.rb +1 -1
  23. data/lib/aasm/persistence/no_brainer_persistence.rb +1 -1
  24. data/lib/aasm/persistence/redis_persistence.rb +1 -1
  25. data/lib/aasm/rspec/transition_from.rb +5 -1
  26. data/lib/aasm/version.rb +1 -1
  27. data/spec/database.rb +5 -0
  28. data/spec/models/active_record/instance_level_skip_validation_example.rb +19 -0
  29. data/spec/models/active_record/person.rb +3 -3
  30. data/spec/models/callbacks/with_state_arg.rb +5 -1
  31. data/spec/models/callbacks/with_state_arg_multiple.rb +4 -1
  32. data/spec/models/simple_example.rb +6 -0
  33. data/spec/spec_helper.rb +10 -0
  34. data/spec/unit/callback_multiple_spec.rb +4 -0
  35. data/spec/unit/callbacks_spec.rb +4 -0
  36. data/spec/unit/complex_example_spec.rb +0 -1
  37. data/spec/unit/event_spec.rb +13 -0
  38. data/spec/unit/persistence/active_record_persistence_multiple_spec.rb +4 -4
  39. data/spec/unit/persistence/active_record_persistence_spec.rb +26 -4
  40. data/spec/unit/rspec_matcher_spec.rb +3 -0
  41. data/spec/unit/simple_example_spec.rb +15 -0
  42. metadata +37 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 90423050620c1cd3228e8f5f67b76be213c9c491
4
- data.tar.gz: 8d583eb68700900b6e0a8c22d6e8b7b0e8714ce7
2
+ SHA256:
3
+ metadata.gz: c02be243049ac08482ee6dd9de9b388d7f965019012f680507b75aee43e1819c
4
+ data.tar.gz: e41809b4fd44cd1d5358e4da499c6b2691caf6a2b6f0b1cf24816458af711522
5
5
  SHA512:
6
- metadata.gz: fb3ca30cbb4d415e5fc9905ae1b9e9ace0b7145ff97f29ce8639a57a99df3df43f3b1626dd9029421e54326085a8e4f5853dfbd21e231c778b3dca058cc980b9
7
- data.tar.gz: 72996c355abefda14839e009f50bdcf900b0acd6d43f3d9eabb4e587390dd67b16be0a9eb66119f7e9d394993d266a0af823dedd6b54ad3e20049d7794fe9bfa
6
+ metadata.gz: c5e49eeff60a68201dccfd988525030946a5f4e2ff080a8818ec729f7bb88291b6f333ccf8666a241dfb72b38a2f30333afbc4d284c3c6103eaab49446630b8e
7
+ data.tar.gz: d2d16d9368d1c8dfd8f50baaea1f07b525798a017fc612c27705161606ae27e1cdd1ea15b979d6d916cfd8abaa81479ff20c72577f8dbbd140dcb78572683845
@@ -0,0 +1,27 @@
1
+ ---
2
+ name: Bug report
3
+ about: Create a report to help us improve
4
+ title: ''
5
+ labels: ''
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ **Describe the bug**
11
+ A clear and concise description of what the bug is.
12
+
13
+ **To Reproduce**
14
+ Steps to reproduce the behavior:
15
+ 1. Go to '...'
16
+ 2. Click on '....'
17
+ 3. Scroll down to '....'
18
+ 4. See error
19
+
20
+ **Expected behavior**
21
+ A clear and concise description of what you expected to happen.
22
+
23
+ **Screenshots**
24
+ If applicable, add screenshots to help explain your problem.
25
+
26
+ **Additional context**
27
+ Add any other context about the problem here.
@@ -0,0 +1,20 @@
1
+ ---
2
+ name: Feature request
3
+ about: Suggest an idea for this project
4
+ title: ''
5
+ labels: ''
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ **Is your feature request related to a problem? Please describe.**
11
+ A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12
+
13
+ **Describe the solution you'd like**
14
+ A clear and concise description of what you want to happen.
15
+
16
+ **Describe alternatives you've considered**
17
+ A clear and concise description of any alternative solutions or features you've considered.
18
+
19
+ **Additional context**
20
+ Add any other context or screenshots about the feature request here.
@@ -2,6 +2,9 @@ sudo: false
2
2
  language: ruby
3
3
  cache: bundler
4
4
 
5
+ jdk:
6
+ - openjdk8
7
+
5
8
  before_install:
6
9
  - rvm list
7
10
  - gem uninstall -v '>= 2' -i $(rvm gemdir)@global -ax bundler || true
@@ -11,23 +14,27 @@ before_install:
11
14
  rvm:
12
15
  - 2.3.0
13
16
  - 2.5.0
17
+ - 2.6.5
18
+ - 2.7.0
14
19
  - jruby-9.1.12.0
15
20
 
16
21
  services:
17
22
  - mongodb
18
23
  - redis-server
19
24
 
20
- addons:
21
- rethinkdb: '2.3.6'
25
+ #addons:
26
+ # rethinkdb: '2.3.4'
22
27
 
23
28
  gemfile:
29
+ - gemfiles/norails.gemfile
24
30
  - gemfiles/rails_3.2.gemfile
25
31
  - gemfiles/rails_4.2.gemfile
26
32
  - gemfiles/rails_4.2_mongoid_5.gemfile
27
- - gemfiles/rails_4.2_nobrainer.gemfile
33
+ # - gemfiles/rails_4.2_nobrainer.gemfile
28
34
  - gemfiles/rails_5.0.gemfile
29
- - gemfiles/rails_5.0_nobrainer.gemfile
35
+ # - gemfiles/rails_5.0_nobrainer.gemfile
30
36
  - gemfiles/rails_5.1.gemfile
37
+ - gemfiles/rails_5.2.gemfile
31
38
 
32
39
  before_script:
33
40
  - mkdir /tmp/dynamodb
@@ -42,27 +49,51 @@ script:
42
49
  matrix:
43
50
  exclude:
44
51
  - rvm: 2.3.0
45
- gemfile: gemfiles/rails_5.0.gemfile
52
+ gemfile: gemfiles/norails.gemfile
46
53
  - rvm: 2.3.0
47
- gemfile: gemfiles/rails_5.0_nobrainer.gemfile
54
+ gemfile: gemfiles/rails_5.0.gemfile
55
+ # - rvm: 2.3.0
56
+ # gemfile: gemfiles/rails_5.0_nobrainer.gemfile
48
57
  - rvm: 2.3.0
49
58
  gemfile: gemfiles/rails_5.1.gemfile
59
+ - rvm: 2.3.0
60
+ gemfile: gemfiles/rails_5.2.gemfile
61
+ - rvm: 2.7.0
62
+ gemfile: gemfiles/rails_5.2.gemfile
63
+ - rvm: 2.6.5
64
+ gemfile: gemfiles/rails_5.2.gemfile
50
65
  - rvm: 2.5.0
51
66
  gemfile: gemfiles/rails_3.2.gemfile
67
+ - rvm: 2.6.5
68
+ gemfile: gemfiles/rails_3.2.gemfile
69
+ - rvm: 2.7.0
70
+ gemfile: gemfiles/rails_3.2.gemfile
52
71
  - rvm: 2.5.0
53
72
  gemfile: gemfiles/rails_4.2.gemfile
73
+ - rvm: 2.6.5
74
+ gemfile: gemfiles/rails_4.2.gemfile
75
+ - rvm: 2.7.0
76
+ gemfile: gemfiles/rails_4.2.gemfile
54
77
  - rvm: 2.5.0
55
78
  gemfile: gemfiles/rails_4.2_mongoid_5.gemfile
56
- - rvm: 2.5.0
57
- gemfile: gemfiles/rails_4.2_nobrainer.gemfile
79
+ - rvm: 2.6.5
80
+ gemfile: gemfiles/rails_4.2_mongoid_5.gemfile
81
+ - rvm: 2.7.0
82
+ gemfile: gemfiles/rails_4.2_mongoid_5.gemfile
83
+ # - rvm: 2.5.0
84
+ # gemfile: gemfiles/rails_4.2_nobrainer.gemfile
85
+ - rvm: jruby-9.1.12.0
86
+ gemfile: gemfiles/norails.gemfile
58
87
  - rvm: jruby-9.1.12.0
59
88
  gemfile: gemfiles/rails_5.0.gemfile
60
89
  - rvm: jruby-9.1.12.0
61
90
  gemfile: gemfiles/rails_5.1.gemfile
62
91
  - rvm: jruby-9.1.12.0
63
- gemfile: gemfiles/rails_4.2_nobrainer.gemfile
64
- - rvm: jruby-9.1.12.0
65
- gemfile: gemfiles/rails_5.0_nobrainer.gemfile
92
+ gemfile: gemfiles/rails_5.2.gemfile
93
+ # - rvm: jruby-9.1.12.0
94
+ # gemfile: gemfiles/rails_4.2_nobrainer.gemfile
95
+ # - rvm: jruby-9.1.12.0
96
+ # gemfile: gemfiles/rails_5.0_nobrainer.gemfile
66
97
 
67
98
  notifications:
68
99
  slack:
data/Appraisals CHANGED
@@ -36,7 +36,7 @@ appraise 'rails_5.0' do
36
36
  gem 'rails', '5.0.0'
37
37
  gem 'mongoid', '~> 6.0'
38
38
  gem 'sequel'
39
- gem 'dynamoid', '~> 1', platforms: :ruby
39
+ gem 'dynamoid', '~> 1.3', platforms: :ruby
40
40
  gem 'aws-sdk', '~> 2', platforms: :ruby
41
41
  gem 'redis-objects'
42
42
  end
@@ -50,7 +50,22 @@ appraise 'rails_5.1' do
50
50
  gem 'rails', '5.1'
51
51
  gem 'mongoid', '~>6.0'
52
52
  gem 'sequel'
53
- gem 'dynamoid', '~> 1', platforms: :ruby
53
+ gem 'dynamoid', '~> 1.3', platforms: :ruby
54
+ gem 'aws-sdk', '~>2', platforms: :ruby
55
+ gem 'redis-objects'
56
+ end
57
+
58
+ appraise 'rails_5.2' do
59
+ gem 'rails', '5.2'
60
+ gem 'mongoid', '~>6.0'
61
+ gem 'sequel'
62
+ gem 'dynamoid', '~>2.2', platforms: :ruby
54
63
  gem 'aws-sdk', '~>2', platforms: :ruby
55
64
  gem 'redis-objects'
56
65
  end
66
+
67
+ appraise 'norails' do
68
+ gem 'rails', install_if: false
69
+ gem 'sequel'
70
+ gem 'redis-objects'
71
+ end
@@ -2,6 +2,39 @@
2
2
 
3
3
  ## unreleased
4
4
 
5
+ ## 5.0.8
6
+
7
+ * Revert Fix for :after_commit within nested transaction because it adds after_commit_action dependency which is dependent on many gems.
8
+
9
+ ## 5.0.7
10
+
11
+ * Fix :after_commit within nested transaction [#666](https://github.com/aasm/aasm/pull/666), thanks to [stokarenko](https://github.com/stokarenko)
12
+ * Add permitted_transitions to group permitted event with state [#664](https://github.com/aasm/aasm/pull/664), thanks to [dnamsons](https://github.com/dnamsons)
13
+ * Add Ruby 2.7.0 & 2.6.5 to Travis CI Test Matrix [#661](https://github.com/aasm/aasm/pull/661), thanks to [the-spectator](https://github.com/the-spectator)
14
+ * Handle InvalidTransition in transition_from matcher [#653](https://github.com/aasm/aasm/pull/653), thanks to [ryanwood](https://github.com/ryanwood)
15
+
16
+ ## 5.0.6
17
+
18
+ * Fix no_direct_assignment, couldn't be turned off pragmatically [#636](https://github.com/aasm/aasm/issues/636)
19
+ * Add instance level validation skip option [#644](https://github.com/aasm/aasm/pull/644), thanks to [Nitin-Salunke](https://github.com/Nitin-Salunke)
20
+ * Fixed aasm.current_event incorrectly yields nil when calling aasm.fire!(:event) [#551](https://github.com/aasm/aasm/issues/551) in [#638](https://github.com/aasm/aasm/pull/638), thanks to [DoubleJarvis](https://github.com/DoubleJarvis)
21
+ * Code Refactor [#634](https://github.com/aasm/aasm/pull/634) , thanks to [rahulknojha](https://github.com/rahulknojha)
22
+ * Fixed callback argument for :before_success & :success callback, [#630](https://github.com/aasm/aasm/pull/630)
23
+
24
+ ## 5.0.5
25
+
26
+ * Independent of ActiveSupport methods, [#627](https://github.com/aasm/aasm/pull/627),
27
+ thanks to [tristandruyen](https://github.com/tristandruyen). Fixes [#508](https://github.com/aasm/aasm/issues/508)
28
+
29
+ ## 5.0.4
30
+
31
+ * Specify dynamoid version for Rails > 5, [#625](https://github.com/aasm/aasm/pull/625),
32
+ thanks to [waghanza](https://github.com/waghanza)
33
+ * Add travis runner for Rails 5.2, [#624](https://github.com/aasm/aasm/pull/624), thanks
34
+ to [waghanza](https://github.com/waghanza)
35
+ * Cleanup Abstract class issue, [#620](https://github.com/aasm/aasm/pull/620), thanks to
36
+ [dennym](https://github.com/dennym)
37
+
5
38
  ## 5.0.3
6
39
 
7
40
  * Fix Abstract class issue, [#619](https://github.com/aasm/aasm/pull/619)
data/Dockerfile CHANGED
@@ -1,9 +1,4 @@
1
- ARG RVM_RUBY_VERSIONS="2.4.0 2.5.0"
2
- ARG RVM_RUBY_DEFAULT="2.4.0"
3
- FROM msati/docker-rvm
4
-
5
- # After Ruby versions are installed we continue as non-root rvm user
6
- USER ${RVM_USER}
1
+ FROM ruby:2.3.4-slim
7
2
 
8
3
  LABEL maintainer="AASM"
9
4
 
data/README.md CHANGED
@@ -3,6 +3,7 @@
3
3
  [![Gem Version](https://badge.fury.io/rb/aasm.svg)](http://badge.fury.io/rb/aasm)
4
4
  [![Build Status](https://travis-ci.org/aasm/aasm.svg?branch=master)](https://travis-ci.org/aasm/aasm)
5
5
  [![Code Climate](https://codeclimate.com/github/aasm/aasm/badges/gpa.svg)](https://codeclimate.com/github/aasm/aasm)
6
+ [![codecov](https://codecov.io/gh/aasm/aasm/branch/master/graph/badge.svg)](https://codecov.io/gh/aasm/aasm)
6
7
 
7
8
  ## Index
8
9
  - [Upgrade from version 3 to 4](#upgrade-from-version-3-to-4)
@@ -29,6 +30,7 @@
29
30
  - [Transaction support](#transaction-support)
30
31
  - [Pessimistic Locking](#pessimistic-locking)
31
32
  - [Column name & migration](#column-name--migration)
33
+ - [Log State Changes](#log-state-changes)
32
34
  - [Inspection](#inspection)
33
35
  - [Warning output](#warning-output)
34
36
  - [RubyMotion support](#rubymotion-support)
@@ -214,13 +216,11 @@ Also, you can pass parameters to events:
214
216
 
215
217
  ```ruby
216
218
  job = Job.new
217
- job.run(:running, :defragmentation)
219
+ job.run(:defragmentation)
218
220
  ```
219
221
 
220
222
  In this case the `set_process` would be called with `:defragmentation` argument.
221
223
 
222
- Note that when passing arguments to a state transition, the first argument must be the desired end state. In the above example, we wish to transition to `:running` state and run the callback with `:defragmentation` argument. You can also pass in `nil` as the desired end state, and AASM will try to transition to the first end state defined for that event.
223
-
224
224
  In case of an error during the event processing the error is rescued and passed to `:error`
225
225
  callback, which can handle it or re-raise it for further propagation.
226
226
 
@@ -436,12 +436,12 @@ job.aasm.current_state # stage3
436
436
  ### Multiple state machines per class
437
437
 
438
438
  Multiple state machines per class are supported. Be aware though that _AASM_ has been
439
- built with one state machine per class in mind. Nonetheless, here's how to do it:
439
+ built with one state machine per class in mind. Nonetheless, here's how to do it (see below). Please note that you will need to specify database columns for where your pertinent states will be stored - we have specified two columns `move_state` and `work_state` in the example below. See the [Column name & migration](https://github.com/aasm/aasm#column-name--migration) section for further info.
440
440
 
441
441
  ```ruby
442
442
  class SimpleMultipleExample
443
443
  include AASM
444
- aasm(:move) do
444
+ aasm(:move, column: 'move_state') do
445
445
  state :standing, initial: true
446
446
  state :walking
447
447
  state :running
@@ -457,7 +457,7 @@ class SimpleMultipleExample
457
457
  end
458
458
  end
459
459
 
460
- aasm(:work) do
460
+ aasm(:work, column: 'work_state') do
461
461
  state :sleeping, initial: true
462
462
  state :processing
463
463
 
@@ -741,6 +741,14 @@ class Job < ActiveRecord::Base
741
741
  end
742
742
  ```
743
743
 
744
+ Also You can skip the validation at instance level with `some_event_name_without_validation!` method.
745
+ With this you have the flexibility of having validation for all your transitions by default and then skip it wherever required.
746
+ Please note that only state column will be updated as mentioned in the above example.
747
+
748
+ ```ruby
749
+ job.run_without_validation!
750
+ ```
751
+
744
752
  If you want to make sure that the _AASM_ column for storing the state is not directly assigned,
745
753
  configure _AASM_ to not allow direct assignment, like this:
746
754
 
@@ -1057,11 +1065,11 @@ this by defining your favorite column name, using `:column` like this:
1057
1065
  class Job < ActiveRecord::Base
1058
1066
  include AASM
1059
1067
 
1060
- aasm column: 'my_state' do
1068
+ aasm column: :my_state do
1061
1069
  ...
1062
1070
  end
1063
1071
 
1064
- aasm :another_state_machine, column: 'second_state' do
1072
+ aasm :another_state_machine, column: :second_state do
1065
1073
  ...
1066
1074
  end
1067
1075
  end
@@ -1082,6 +1090,13 @@ class AddJobState < ActiveRecord::Migration
1082
1090
  end
1083
1091
  ```
1084
1092
 
1093
+ ### Log State Changes
1094
+
1095
+ Logging state change can be done using [paper_trail](https://github.com/paper-trail-gem/paper_trail) gem
1096
+
1097
+ Example of implementation can be found here [https://github.com/nitsujri/aasm-papertrail-example](https://github.com/nitsujri/aasm-papertrail-example)
1098
+
1099
+
1085
1100
  ### Inspection
1086
1101
 
1087
1102
  AASM supports query methods for states and events
@@ -1126,6 +1141,10 @@ job = Job.new
1126
1141
  job.aasm.states(permitted: true).map(&:name)
1127
1142
  #=> [:running]
1128
1143
 
1144
+ # List all the permitted transitions(event and state pairs) from initial state
1145
+ job.aasm.permitted_transitions
1146
+ #=> [{ :event => :run, :state => :running }]
1147
+
1129
1148
  job.run
1130
1149
  job.aasm.states(permitted: true).map(&:name)
1131
1150
  #=> [:sleeping]
@@ -1193,7 +1212,7 @@ the 'instance method symbol / string' way whenever possible when defining guardi
1193
1212
  #### RSpec
1194
1213
 
1195
1214
  AASM provides some matchers for [RSpec](http://rspec.info):
1196
- *`transition_from`,
1215
+ * `transition_from`,
1197
1216
  * `have_state`, `allow_event`
1198
1217
  * and `allow_transition_to`.
1199
1218
 
@@ -23,6 +23,8 @@ Gem::Specification.new do |s|
23
23
  s.add_development_dependency 'rspec', ">= 3"
24
24
  s.add_development_dependency 'generator_spec'
25
25
  s.add_development_dependency 'appraisal'
26
+ s.add_development_dependency "simplecov"
27
+ s.add_development_dependency "codecov", ">= 0.1.10"
26
28
 
27
29
  # debugging
28
30
  # s.add_development_dependency 'debugger'
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "sqlite3", "~> 1.3", ">= 1.3.5", platforms: :ruby
6
+ gem "rails", install_if: false
7
+ gem "sequel"
8
+ gem "redis-objects"
9
+
10
+ gemspec path: "../"
@@ -6,7 +6,7 @@ gem "sqlite3", "~> 1.3.5", platforms: :ruby
6
6
  gem "rails", "5.0.0"
7
7
  gem "mongoid", "~> 6.0"
8
8
  gem "sequel"
9
- gem "dynamoid", "~> 1", platforms: :ruby
9
+ gem "dynamoid", "~> 1.3", platforms: :ruby
10
10
  gem "aws-sdk", "~> 2", platforms: :ruby
11
11
  gem "redis-objects"
12
12
 
@@ -6,7 +6,7 @@ gem "sqlite3", "~> 1.3.5", platforms: :ruby
6
6
  gem "rails", "5.1"
7
7
  gem "mongoid", "~>6.0"
8
8
  gem "sequel"
9
- gem "dynamoid", "~> 1", platforms: :ruby
9
+ gem "dynamoid", "~> 1.3", platforms: :ruby
10
10
  gem "aws-sdk", "~>2", platforms: :ruby
11
11
  gem "redis-objects"
12
12
 
@@ -0,0 +1,13 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "sqlite3", "~> 1.3.5", platforms: :ruby
6
+ gem "rails", "5.2"
7
+ gem "mongoid", "~>6.0"
8
+ gem "sequel"
9
+ gem "dynamoid", "~>2.2", platforms: :ruby
10
+ gem "aws-sdk", "~>2", platforms: :ruby
11
+ gem "redis-objects"
12
+
13
+ gemspec path: "../"
@@ -99,25 +99,10 @@ private
99
99
  begin
100
100
  old_state = aasm(state_machine_name).state_object_for_name(aasm(state_machine_name).current_state)
101
101
 
102
- event.fire_global_callbacks(
103
- :before_all_events,
104
- self,
105
- *process_args(event, aasm(state_machine_name).current_state, *args)
106
- )
107
-
108
- # new event before callback
109
- event.fire_callbacks(
110
- :before,
111
- self,
112
- *process_args(event, aasm(state_machine_name).current_state, *args)
113
- )
102
+ fire_default_callbacks(event, *process_args(event, aasm(state_machine_name).current_state, *args))
114
103
 
115
104
  if may_fire_to = event.may_fire?(self, *args)
116
- old_state.fire_callbacks(:before_exit, self,
117
- *process_args(event, aasm(state_machine_name).current_state, *args))
118
- old_state.fire_callbacks(:exit, self,
119
- *process_args(event, aasm(state_machine_name).current_state, *args))
120
-
105
+ fire_exit_callbacks(old_state, *process_args(event, aasm(state_machine_name).current_state, *args))
121
106
  if new_state_name = event.fire(self, {:may_fire => may_fire_to}, *args)
122
107
  aasm_fired(state_machine_name, event, old_state, new_state_name, options, *args, &block)
123
108
  else
@@ -137,25 +122,44 @@ private
137
122
  end
138
123
  end
139
124
 
125
+ def fire_default_callbacks(event, *processed_args)
126
+ event.fire_global_callbacks(
127
+ :before_all_events,
128
+ self,
129
+ *processed_args
130
+ )
131
+
132
+ # new event before callback
133
+ event.fire_callbacks(
134
+ :before,
135
+ self,
136
+ *processed_args
137
+ )
138
+ end
139
+
140
+ def fire_exit_callbacks(old_state, *processed_args)
141
+ old_state.fire_callbacks(:before_exit, self, *processed_args)
142
+ old_state.fire_callbacks(:exit, self, *processed_args)
143
+ end
144
+
140
145
  def aasm_fired(state_machine_name, event, old_state, new_state_name, options, *args)
141
146
  persist = options[:persist]
142
147
 
143
148
  new_state = aasm(state_machine_name).state_object_for_name(new_state_name)
149
+ callback_args = process_args(event, aasm(state_machine_name).current_state, *args)
144
150
 
145
- new_state.fire_callbacks(:before_enter, self,
146
- *process_args(event, aasm(state_machine_name).current_state, *args))
151
+ new_state.fire_callbacks(:before_enter, self, *callback_args)
147
152
 
148
- new_state.fire_callbacks(:enter, self,
149
- *process_args(event, aasm(state_machine_name).current_state, *args)) # TODO: remove for AASM 4?
153
+ new_state.fire_callbacks(:enter, self, *callback_args) # TODO: remove for AASM 4?
150
154
 
151
155
  persist_successful = true
152
156
  if persist
153
157
  persist_successful = aasm(state_machine_name).set_current_state_with_persistence(new_state_name)
154
158
  if persist_successful
155
159
  yield if block_given?
156
- event.fire_callbacks(:before_success, self)
160
+ event.fire_callbacks(:before_success, self, *callback_args)
157
161
  event.fire_transition_callbacks(self, *process_args(event, old_state.name, *args))
158
- event.fire_callbacks(:success, self)
162
+ event.fire_callbacks(:success, self, *callback_args)
159
163
  end
160
164
  else
161
165
  aasm(state_machine_name).current_state = new_state_name
@@ -168,10 +172,8 @@ private
168
172
  end
169
173
 
170
174
  if persist_successful
171
- old_state.fire_callbacks(:after_exit, self,
172
- *process_args(event, aasm(state_machine_name).current_state, *args))
173
- new_state.fire_callbacks(:after_enter, self,
174
- *process_args(event, aasm(state_machine_name).current_state, *args))
175
+ old_state.fire_callbacks(:after_exit, self, *callback_args)
176
+ new_state.fire_callbacks(:after_enter, self, *callback_args)
175
177
  event.fire_callbacks(
176
178
  :after,
177
179
  self,
@@ -54,25 +54,18 @@ module AASM
54
54
  # make sure to raise an error if no_direct_assignment is enabled
55
55
  # and attribute is directly assigned though
56
56
  aasm_name = @name
57
- return true if should_not_define_method(klass) && !@state_machine.config.no_direct_assignment
58
- klass.send :define_method, "#{@state_machine.config.column}=", ->(state_name) do
59
- if self.class.aasm(:"#{aasm_name}").state_machine.config.no_direct_assignment
60
- raise AASM::NoDirectAssignmentError.new(
61
- 'direct assignment of AASM column has been disabled (see AASM configuration for this class)'
62
- )
63
- else
64
- super(state_name)
57
+
58
+ if @state_machine.config.no_direct_assignment
59
+ @klass.send(:define_method, "#{@state_machine.config.column}=") do |state_name|
60
+ if self.class.aasm(:"#{aasm_name}").state_machine.config.no_direct_assignment
61
+ raise AASM::NoDirectAssignmentError.new('direct assignment of AASM column has been disabled (see AASM configuration for this class)')
62
+ else
63
+ super(state_name)
64
+ end
65
65
  end
66
66
  end
67
67
  end
68
68
 
69
- def should_not_define_method(klass)
70
- (klass.methods.include?(:abstract_class) &&
71
- klass.abstract_class) ||
72
- (klass.superclass.methods.include?(:abstract_class) &&
73
- klass.superclass.abstract_class)
74
- end
75
-
76
69
  # This method is both a getter and a setter
77
70
  def attribute_name(column_name=nil)
78
71
  if column_name
@@ -142,6 +135,8 @@ module AASM
142
135
  aasm_fire_event(aasm_name, event, {:persist => false}, *args, &block)
143
136
  end
144
137
 
138
+ skip_instance_level_validation(event, name, aasm_name, klass)
139
+
145
140
  # Create aliases for the event methods. Keep the old names to maintain backwards compatibility.
146
141
  if namespace?
147
142
  klass.send(:alias_method, "may_#{name}_#{namespace}?", "may_#{name}?")
@@ -257,5 +252,20 @@ module AASM
257
252
  end
258
253
  end
259
254
 
255
+ def skip_instance_level_validation(event, name, aasm_name, klass)
256
+ # Overrides the skip_validation config for an instance (If skip validation is set to false in original config) and
257
+ # restores it back to the original value after the event is fired.
258
+ safely_define_method klass, "#{name}_without_validation!", ->(*args, &block) do
259
+ original_config = AASM::StateMachineStore.fetch(self.class, true).machine(aasm_name).config.skip_validation_on_save
260
+ begin
261
+ AASM::StateMachineStore.fetch(self.class, true).machine(aasm_name).config.skip_validation_on_save = true unless original_config
262
+ aasm(aasm_name).current_event = :"#{name}!"
263
+ aasm_fire_event(aasm_name, event, {:persist => true}, *args, &block)
264
+ ensure
265
+ AASM::StateMachineStore.fetch(self.class, true).machine(aasm_name).config.skip_validation_on_save = original_config
266
+ end
267
+ end
268
+ end
269
+
260
270
  end
261
271
  end
@@ -131,13 +131,13 @@ module AASM::Core
131
131
 
132
132
  if to_state == ::AASM::NO_VALUE
133
133
  to_state = nil
134
- elsif to_state.respond_to?(:to_sym) && transitions.map(&:to).flatten.include?(to_state.to_sym)
135
- # nop, to_state is a valid to-state
136
- else
134
+ elsif !(to_state.respond_to?(:to_sym) && transitions.map(&:to).flatten.include?(to_state.to_sym))
137
135
  # to_state is an argument
138
136
  args.unshift(to_state)
139
137
  to_state = nil
140
138
  end
139
+
140
+ # nop, to_state is a valid to-state
141
141
 
142
142
  transitions.each do |transition|
143
143
  next if to_state and !Array(transition.to).include?(to_state)
@@ -78,6 +78,17 @@ module AASM
78
78
  events
79
79
  end
80
80
 
81
+ def permitted_transitions
82
+ events(permitted: true).flat_map do |event|
83
+ available_transitions = event.transitions_from_state(current_state)
84
+ allowed_transitions = available_transitions.select { |t| t.allowed?(@instance) }
85
+
86
+ allowed_transitions.map do |transition|
87
+ { event: event.name, state: transition.to }
88
+ end
89
+ end
90
+ end
91
+
81
92
  def state_object_for_name(name)
82
93
  obj = @instance.class.aasm(@name).states.find {|s| s.name == name}
83
94
  raise AASM::UndefinedState, "State :#{name} doesn't exist" if obj.nil?
@@ -91,7 +102,7 @@ module AASM
91
102
  when Proc
92
103
  state.call(@instance)
93
104
  else
94
- raise NotImplementedError, "Unrecognized state-type given. Expected Symbol, String, or Proc."
105
+ raise NotImplementedError, "Unrecognized state-type given. Expected Symbol, String, or Proc."
95
106
  end
96
107
  end
97
108
 
@@ -104,11 +115,12 @@ module AASM
104
115
  end
105
116
 
106
117
  def fire(event_name, *args, &block)
107
- @instance.send(:aasm_fire_event, @name, event_name, {persist: false}, *args, &block)
118
+ @instance.send(event_name, *args, &block)
108
119
  end
109
120
 
110
121
  def fire!(event_name, *args, &block)
111
- @instance.send(:aasm_fire_event, @name, event_name, {persist: true}, *args, &block)
122
+ event_name = event_name.to_s.+("!").to_sym
123
+ @instance.send(event_name, *args, &block)
112
124
  end
113
125
 
114
126
  def set_current_state_with_persistence(state)
@@ -141,7 +141,8 @@ module AASM
141
141
 
142
142
  def aasm_column_is_blank?(state_machine_name)
143
143
  attribute_name = self.class.aasm(state_machine_name).attribute_name
144
- attribute_names.include?(attribute_name.to_s) && send(attribute_name).blank?
144
+ attribute_names.include?(attribute_name.to_s) &&
145
+ (send(attribute_name).respond_to?(:empty?) ? !!send(attribute_name).empty? : !send(attribute_name))
145
146
  end
146
147
 
147
148
  def aasm_validate_states
@@ -34,7 +34,7 @@ module AASM
34
34
  # This allows for nil aasm states - be sure to add validation to your model
35
35
  def aasm_read_state(name=:default)
36
36
  state = send(self.class.aasm(name).attribute_name)
37
- if state.blank?
37
+ if !state || state.empty?
38
38
  aasm_new_record? ? aasm(name).determine_state_name(self.class.aasm(name).initial_state) : nil
39
39
  else
40
40
  state.to_sym
@@ -77,7 +77,8 @@ module AASM
77
77
  #
78
78
  def aasm_ensure_initial_state
79
79
  AASM::StateMachineStore.fetch(self.class, true).machine_names.each do |state_machine_name|
80
- send("#{self.class.aasm(state_machine_name).attribute_name}=", aasm(state_machine_name).enter_initial_state.to_s) if send(self.class.aasm(state_machine_name).attribute_name).blank?
80
+ next if !send(self.class.aasm(state_machine_name).attribute_name) || send(self.class.aasm(state_machine_name).attribute_name).empty?
81
+ send("#{self.class.aasm(state_machine_name).attribute_name}=", aasm(state_machine_name).enter_initial_state.to_s)
81
82
  end
82
83
  end
83
84
  end # InstanceMethods
@@ -83,7 +83,7 @@ module AASM
83
83
  #
84
84
  def aasm_ensure_initial_state
85
85
  AASM::StateMachineStore.fetch(self.class, true).machine_names.each do |state_machine_name|
86
- aasm(state_machine_name).enter_initial_state if send(self.class.aasm(state_machine_name).attribute_name).blank?
86
+ aasm(state_machine_name).enter_initial_state if !send(self.class.aasm(state_machine_name).attribute_name) || send(self.class.aasm(state_machine_name).attribute_name).empty?
87
87
  end
88
88
  end
89
89
  end # InstanceMethods
@@ -106,7 +106,7 @@ module AASM
106
106
  # mongoid has_many relationship does not load child object attributes when
107
107
  # only ids are loaded, for example parent.child_ids will not load child object attributes.
108
108
  # This feature is introduced in mongoid > 4.
109
- if attribute_names.include?(attribute_name) && attributes[attribute_name].blank?
109
+ if attribute_names.include?(attribute_name) && !attributes[attribute_name] || attributes[attribute_name].empty?
110
110
  # attribute_missing? is defined in mongoid > 4
111
111
  return if Mongoid::VERSION.to_f >= 4 && attribute_missing?(attribute_name)
112
112
  send("#{self.class.aasm(state_machine_name).attribute_name}=", aasm(state_machine_name).enter_initial_state.to_s)
@@ -96,7 +96,7 @@ module AASM
96
96
  def aasm_ensure_initial_state
97
97
  AASM::StateMachineStore.fetch(self.class, true).machine_names.each do |name|
98
98
  aasm_column = self.class.aasm(name).attribute_name
99
- aasm(name).enter_initial_state if read_attribute(aasm_column).blank?
99
+ aasm(name).enter_initial_state if !read_attribute(aasm_column) || read_attribute(aasm_column).empty?
100
100
  end
101
101
  end
102
102
  end # InstanceMethods
@@ -69,7 +69,7 @@ module AASM
69
69
  def aasm_ensure_initial_state
70
70
  AASM::StateMachineStore.fetch(self.class, true).machine_names.each do |name|
71
71
  aasm_column = self.class.aasm(name).attribute_name
72
- aasm(name).enter_initial_state if send(aasm_column).value.blank?
72
+ aasm(name).enter_initial_state if !send(aasm_column).value || send(aasm_column).value.empty?
73
73
  end
74
74
  end
75
75
 
@@ -2,7 +2,11 @@ RSpec::Matchers.define :transition_from do |from_state|
2
2
  match do |obj|
3
3
  @state_machine_name ||= :default
4
4
  obj.aasm(@state_machine_name).current_state = from_state.to_sym
5
- obj.send(@event, *@args) && obj.aasm(@state_machine_name).current_state == @to_state.to_sym
5
+ begin
6
+ obj.send(@event, *@args) && obj.aasm(@state_machine_name).current_state == @to_state.to_sym
7
+ rescue AASM::InvalidTransition
8
+ false
9
+ end
6
10
  end
7
11
 
8
12
  chain :on do |state_machine_name|
@@ -1,3 +1,3 @@
1
1
  module AASM
2
- VERSION = "5.0.3"
2
+ VERSION = "5.0.8"
3
3
  end
@@ -51,4 +51,9 @@ ActiveRecord::Migration.suppress_messages do
51
51
  t.string "search"
52
52
  t.string "sync"
53
53
  end
54
+
55
+ ActiveRecord::Migration.create_table "instance_level_skip_validation_examples", :force => true do |t|
56
+ t.string "state"
57
+ t.string "some_string"
58
+ end
54
59
  end
@@ -0,0 +1,19 @@
1
+ class InstanceLevelSkipValidationExample < ActiveRecord::Base
2
+ include AASM
3
+
4
+ aasm :state do
5
+ state :new, :initial => true
6
+ state :draft
7
+ state :complete
8
+
9
+ event :set_draft do
10
+ transitions from: :new, to: :draft
11
+ end
12
+
13
+ event :complete do
14
+ transitions from: %i[draft new], to: :complete
15
+ end
16
+ end
17
+
18
+ validates :some_string, presence: true
19
+ end
@@ -1,7 +1,4 @@
1
1
  class Base < ActiveRecord::Base
2
- self.abstract_class = true
3
- self.table_name = 'users'
4
-
5
2
  include AASM
6
3
 
7
4
  aasm column: 'status' do
@@ -16,6 +13,9 @@ class Base < ActiveRecord::Base
16
13
  transitions from: :active, to: :inactive
17
14
  end
18
15
  end
16
+
17
+ self.abstract_class = true
18
+ self.table_name = 'users'
19
19
  end
20
20
 
21
21
 
@@ -8,7 +8,7 @@ module Callbacks
8
8
  state :closed
9
9
  state :out_to_lunch
10
10
 
11
- event :close, :before => :before_method, :after => :after_method do
11
+ event :close, :before => :before_method, :after => :after_method, :before_success => :before_success_method, :success => :success_method3 do
12
12
  transitions :to => :closed, :from => [:open], :after => :transition_method, :success => :success_method
13
13
  transitions :to => :out_to_lunch, :from => [:open], :after => :transition_method2, :success => :success_method2
14
14
  end
@@ -16,6 +16,8 @@ module Callbacks
16
16
 
17
17
  def before_method(arg); end
18
18
 
19
+ def before_success_method(arg); end
20
+
19
21
  def after_method(arg); end
20
22
 
21
23
  def transition_method(arg); end
@@ -26,5 +28,7 @@ module Callbacks
26
28
 
27
29
  def success_method2(arg); end
28
30
 
31
+ def success_method3(arg); end
32
+
29
33
  end
30
34
  end
@@ -8,7 +8,7 @@ module Callbacks
8
8
  state :closed
9
9
  state :out_to_lunch
10
10
 
11
- event :close, :before => :before_method, :after => :after_method do
11
+ event :close, :before => :before_method, :after => :after_method, :before_success => :before_success_method, :success => :success_method do
12
12
  transitions :to => :closed, :from => [:open], :after => :transition_method
13
13
  transitions :to => :out_to_lunch, :from => [:open], :after => :transition_method2
14
14
  end
@@ -16,11 +16,14 @@ module Callbacks
16
16
 
17
17
  def before_method(arg); end
18
18
 
19
+ def before_success_method(arg); end
20
+
19
21
  def after_method(arg); end
20
22
 
21
23
  def transition_method(arg); end
22
24
 
23
25
  def transition_method2(arg); end
24
26
 
27
+ def success_method(arg); end
25
28
  end
26
29
  end
@@ -3,11 +3,17 @@ class SimpleExample
3
3
  aasm do
4
4
  state :initialised, :initial => true
5
5
  state :filled_out
6
+ state :denied
6
7
  state :authorised
7
8
 
8
9
  event :fill_out do
9
10
  transitions :from => :initialised, :to => :filled_out
10
11
  end
12
+
13
+ event :deny do
14
+ transitions from: :initialised, to: :denied
15
+ end
16
+
11
17
  event :authorise do
12
18
  transitions :from => :filled_out, :to => :authorised
13
19
  end
@@ -1,3 +1,13 @@
1
+ require 'simplecov'
2
+ SimpleCov.start do
3
+ add_filter '/spec/'
4
+ end
5
+
6
+ if ENV['CI'] == 'true'
7
+ require 'codecov'
8
+ SimpleCov.formatter = SimpleCov::Formatter::Codecov
9
+ end
10
+
1
11
  $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)))
2
12
  $LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib')))
3
13
  require 'aasm'
@@ -154,6 +154,8 @@ describe 'callbacks for the new DSL' do
154
154
  expect(cb).to receive(:before_method).with(:arg1).once.ordered
155
155
  expect(cb).to receive(:transition_method).never
156
156
  expect(cb).to receive(:transition_method2).with(:arg1).once.ordered
157
+ expect(cb).to receive(:before_success_method).with(:arg1).once.ordered
158
+ expect(cb).to receive(:success_method).with(:arg1).once.ordered
157
159
  expect(cb).to receive(:after_method).with(:arg1).once.ordered
158
160
  cb.close!(:out_to_lunch, :arg1)
159
161
 
@@ -161,6 +163,8 @@ describe 'callbacks for the new DSL' do
161
163
  some_object = double('some object')
162
164
  expect(cb).to receive(:before_method).with(some_object).once.ordered
163
165
  expect(cb).to receive(:transition_method2).with(some_object).once.ordered
166
+ expect(cb).to receive(:before_success_method).with(some_object).once.ordered
167
+ expect(cb).to receive(:success_method).with(some_object).once.ordered
164
168
  expect(cb).to receive(:after_method).with(some_object).once.ordered
165
169
  cb.close!(:out_to_lunch, some_object)
166
170
  end
@@ -315,7 +315,9 @@ describe 'callbacks for the new DSL' do
315
315
  expect(cb).to receive(:before_method).with(:arg1).once.ordered
316
316
  expect(cb).to receive(:transition_method).with(:arg1).once.ordered
317
317
  expect(cb).to receive(:transition_method).never
318
+ expect(cb).to receive(:before_success_method).with(:arg1).once.ordered
318
319
  expect(cb).to receive(:success_method).with(:arg1).once.ordered
320
+ expect(cb).to receive(:success_method3).with(:arg1).once.ordered
319
321
  expect(cb).to receive(:success_method).never
320
322
  expect(cb).to receive(:after_method).with(:arg1).once.ordered
321
323
  cb.close!(:arg1)
@@ -325,7 +327,9 @@ describe 'callbacks for the new DSL' do
325
327
  expect(cb).to receive(:before_method).with(some_object).once.ordered
326
328
  expect(cb).to receive(:transition_method).with(some_object).once.ordered
327
329
  expect(cb).to receive(:transition_method).never
330
+ expect(cb).to receive(:before_success_method).with(some_object).once.ordered
328
331
  expect(cb).to receive(:success_method).with(some_object).once.ordered
332
+ expect(cb).to receive(:success_method3).with(some_object).once.ordered
329
333
  expect(cb).to receive(:success_method).never
330
334
  expect(cb).to receive(:after_method).with(some_object).once.ordered
331
335
  cb.close!(some_object)
@@ -90,5 +90,4 @@ describe 'when being unsuspended' do
90
90
  it "should not be able to fire unknown events" do
91
91
  expect(auth.aasm.may_fire_event?(:unknown)).to be false
92
92
  end
93
-
94
93
  end
@@ -294,6 +294,19 @@ describe 'current event' do
294
294
  pe.wakeup!
295
295
  expect(pe.aasm.current_event).to eql :wakeup!
296
296
  end
297
+
298
+ describe "when calling events with fire/fire!" do
299
+ it "fire should populate aasm.current_event and transition (sleeping to showering)" do
300
+ pe.aasm.fire(:wakeup)
301
+ expect(pe.aasm.current_event).to eq :wakeup
302
+ expect(pe.aasm.current_state).to eq :showering
303
+ end
304
+ it "fire! should populate aasm.current_event and transition (sleeping to showering)" do
305
+ pe.aasm.fire!(:wakeup)
306
+ expect(pe.aasm.current_event).to eq :wakeup!
307
+ expect(pe.aasm.current_state).to eq :showering
308
+ end
309
+ end
297
310
  end
298
311
 
299
312
  describe 'parametrised events' do
@@ -359,13 +359,13 @@ if defined?(ActiveRecord)
359
359
 
360
360
  # allow it temporarily
361
361
  MultipleNoDirectAssignment.aasm(:left).state_machine.config.no_direct_assignment = false
362
- obj.aasm_state = :pending
363
- expect(obj.aasm_state.to_sym).to eql :pending
362
+ obj.aasm_state = :running
363
+ expect(obj.aasm_state.to_sym).to eql :running
364
364
 
365
365
  # and forbid it again
366
366
  MultipleNoDirectAssignment.aasm(:left).state_machine.config.no_direct_assignment = true
367
- expect {obj.aasm_state = :running}.to raise_error(AASM::NoDirectAssignmentError)
368
- expect(obj.aasm_state.to_sym).to eql :pending
367
+ expect {obj.aasm_state = :pending}.to raise_error(AASM::NoDirectAssignmentError)
368
+ expect(obj.aasm_state.to_sym).to eql :running
369
369
  end
370
370
  end # direct assignment
371
371
 
@@ -393,13 +393,13 @@ if defined?(ActiveRecord)
393
393
 
394
394
  # allow it temporarily
395
395
  NoDirectAssignment.aasm.state_machine.config.no_direct_assignment = false
396
- obj.aasm_state = :pending
397
- expect(obj.aasm_state.to_sym).to eql :pending
396
+ obj.aasm_state = :running
397
+ expect(obj.aasm_state.to_sym).to eql :running
398
398
 
399
399
  # and forbid it again
400
400
  NoDirectAssignment.aasm.state_machine.config.no_direct_assignment = true
401
- expect {obj.aasm_state = :running}.to raise_error(AASM::NoDirectAssignmentError)
402
- expect(obj.aasm_state.to_sym).to eql :pending
401
+ expect {obj.aasm_state = :pending}.to raise_error(AASM::NoDirectAssignmentError)
402
+ expect(obj.aasm_state.to_sym).to eql :running
403
403
  end
404
404
  end # direct assignment
405
405
 
@@ -748,4 +748,26 @@ if defined?(ActiveRecord)
748
748
  expect { job.run }.to raise_error(AASM::InvalidTransition)
749
749
  end
750
750
  end
751
+
752
+ describe 'testing the instance_level skip validation with _without_validation method' do
753
+ let(:example) do
754
+ obj = InstanceLevelSkipValidationExample.new(state: 'new')
755
+ obj.save(validate: false)
756
+ obj
757
+ end
758
+
759
+ it 'should be able to change the state with invalid record' do
760
+ expect(example.valid?).to be_falsey
761
+ expect(example.complete!).to be_falsey
762
+ expect(example.complete_without_validation!).to be_truthy
763
+ expect(example.state).to eq('complete')
764
+ end
765
+
766
+ it 'shouldn\'t affect the behaviour of existing method after calling _without_validation! method' do
767
+ expect(example.set_draft!).to be_falsey
768
+ expect(example.set_draft_without_validation!).to be_truthy
769
+ expect(example.state).to eq('draft')
770
+ expect(example.complete!).to be_falsey
771
+ end
772
+ end
751
773
  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)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aasm
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.3
4
+ version: 5.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thorsten Boettger
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2019-04-21 00:00:00.000000000 Z
12
+ date: 2020-03-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: concurrent-ruby
@@ -95,6 +95,34 @@ dependencies:
95
95
  - - ">="
96
96
  - !ruby/object:Gem::Version
97
97
  version: '0'
98
+ - !ruby/object:Gem::Dependency
99
+ name: simplecov
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ - !ruby/object:Gem::Dependency
113
+ name: codecov
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: 0.1.10
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: 0.1.10
98
126
  - !ruby/object:Gem::Dependency
99
127
  name: pry
100
128
  requirement: !ruby/object:Gem::Requirement
@@ -117,6 +145,8 @@ extensions: []
117
145
  extra_rdoc_files: []
118
146
  files:
119
147
  - ".document"
148
+ - ".github/ISSUE_TEMPLATE/bug_report.md"
149
+ - ".github/ISSUE_TEMPLATE/feature_request.md"
120
150
  - ".gitignore"
121
151
  - ".travis.yml"
122
152
  - API
@@ -137,6 +167,7 @@ files:
137
167
  - aasm.gemspec
138
168
  - callbacks.txt
139
169
  - docker-compose.yml
170
+ - gemfiles/norails.gemfile
140
171
  - gemfiles/rails_3.2.gemfile
141
172
  - gemfiles/rails_4.2.gemfile
142
173
  - gemfiles/rails_4.2_mongoid_5.gemfile
@@ -144,6 +175,7 @@ files:
144
175
  - gemfiles/rails_5.0.gemfile
145
176
  - gemfiles/rails_5.0_nobrainer.gemfile
146
177
  - gemfiles/rails_5.1.gemfile
178
+ - gemfiles/rails_5.2.gemfile
147
179
  - lib/aasm.rb
148
180
  - lib/aasm/aasm.rb
149
181
  - lib/aasm/base.rb
@@ -205,6 +237,7 @@ files:
205
237
  - spec/models/active_record/derivate_new_dsl.rb
206
238
  - spec/models/active_record/false_state.rb
207
239
  - spec/models/active_record/gate.rb
240
+ - spec/models/active_record/instance_level_skip_validation_example.rb
208
241
  - spec/models/active_record/invalid_persistor.rb
209
242
  - spec/models/active_record/localizer_test_model.rb
210
243
  - spec/models/active_record/no_direct_assignment.rb
@@ -390,8 +423,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
390
423
  - !ruby/object:Gem::Version
391
424
  version: '0'
392
425
  requirements: []
393
- rubyforge_project:
394
- rubygems_version: 2.6.14
426
+ rubygems_version: 3.1.2
395
427
  signing_key:
396
428
  specification_version: 4
397
429
  summary: State machine mixin for Ruby objects
@@ -408,6 +440,7 @@ test_files:
408
440
  - spec/models/active_record/derivate_new_dsl.rb
409
441
  - spec/models/active_record/false_state.rb
410
442
  - spec/models/active_record/gate.rb
443
+ - spec/models/active_record/instance_level_skip_validation_example.rb
411
444
  - spec/models/active_record/invalid_persistor.rb
412
445
  - spec/models/active_record/localizer_test_model.rb
413
446
  - spec/models/active_record/no_direct_assignment.rb