aasm 5.1.0 → 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 (46) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +0 -11
  3. data/Appraisals +5 -5
  4. data/CHANGELOG.md +17 -0
  5. data/README.md +78 -6
  6. data/aasm.gemspec +1 -1
  7. data/gemfiles/rails_4.2.gemfile +1 -1
  8. data/gemfiles/rails_4.2_mongoid_5.gemfile +1 -1
  9. data/gemfiles/rails_5.0.gemfile +1 -1
  10. data/gemfiles/rails_5.1.gemfile +1 -1
  11. data/gemfiles/rails_5.2.gemfile +1 -1
  12. data/lib/aasm/base.rb +30 -11
  13. data/lib/aasm/configuration.rb +3 -0
  14. data/lib/aasm/core/event.rb +7 -2
  15. data/lib/aasm/core/state.rb +6 -5
  16. data/lib/aasm/core/transition.rb +1 -1
  17. data/lib/aasm/dsl_helper.rb +24 -22
  18. data/lib/aasm/instance_base.rb +1 -1
  19. data/lib/aasm/localizer.rb +13 -3
  20. data/lib/aasm/persistence/active_record_persistence.rb +18 -13
  21. data/lib/aasm/persistence/base.rb +13 -2
  22. data/lib/aasm/persistence/orm.rb +1 -1
  23. data/lib/aasm/version.rb +1 -1
  24. data/lib/aasm.rb +0 -2
  25. data/spec/database.rb +9 -11
  26. data/spec/en.yml +0 -3
  27. data/spec/{en_deprecated_style.yml → localizer_test_model_deprecated_style.yml} +6 -3
  28. data/spec/localizer_test_model_new_style.yml +11 -0
  29. data/spec/models/active_record/localizer_test_model.rb +11 -3
  30. data/spec/models/active_record/namespaced.rb +16 -0
  31. data/spec/models/active_record/timestamp_example.rb +16 -0
  32. data/spec/models/default_state.rb +1 -1
  33. data/spec/models/mongoid/timestamp_example_mongoid.rb +20 -0
  34. data/spec/models/timestamps_example.rb +19 -0
  35. data/spec/models/timestamps_with_named_machine_example.rb +13 -0
  36. data/spec/spec_helper.rb +5 -0
  37. data/spec/unit/api_spec.rb +4 -0
  38. data/spec/unit/inspection_multiple_spec.rb +9 -5
  39. data/spec/unit/inspection_spec.rb +7 -3
  40. data/spec/unit/localizer_spec.rb +49 -18
  41. data/spec/unit/persistence/active_record_persistence_multiple_spec.rb +17 -0
  42. data/spec/unit/persistence/active_record_persistence_spec.rb +12 -0
  43. data/spec/unit/persistence/mongoid_persistence_spec.rb +12 -0
  44. data/spec/unit/state_spec.rb +21 -5
  45. data/spec/unit/timestamps_spec.rb +32 -0
  46. metadata +20 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: be8ee23b312066a6b90211161857cb2c461f20e9b1e3e93f955d6b8caeb6f497
4
- data.tar.gz: 47c63523fc92f0fdc823024f632f27cab4453c4c2c9c7e277c45dea0f170250f
3
+ metadata.gz: 6e3ec7032fd9c8368ddfb4bed4e931edc5f9d96c02a69f89f7ee26913f7d8698
4
+ data.tar.gz: ddb4ef39501440da1869426eda3b4359e37eeef67b464c9e0d660e9f353510f6
5
5
  SHA512:
6
- metadata.gz: 258182cd645528de747eff39a70bcd697b5f965e49890ce369804aba0fb4c08739ff5259efef9cdde405b819765becb451ba4a6994f74dc89f0581c387d84ef1
7
- data.tar.gz: 9408e99df7783505a8a67d4d54b0d5f3660b991790db7bad46598734ed33d1d7f1b5e463f67d435c0de15d0d1ef020023f8900781a72a40bcc85c35d76c8cf22
6
+ metadata.gz: c294de071cad6569f855af1455c9d0281622ca5c9a3df0466baacaca569d8974718eb46d4c06e674f54629a77e2634d69829ee2910612ba146b4aaf786891544
7
+ data.tar.gz: a7b0c176cec262ad9d89538fe43e6df484f4d79328f85e853dcc9fe6b6ce9a9629f802e7de14659e5c91135a3a4df09a6066011983b1936eff06b17657c24cc5
data/.travis.yml CHANGED
@@ -12,7 +12,6 @@ before_install:
12
12
  - bundle _1.16.1_ install
13
13
 
14
14
  rvm:
15
- - 2.3.0
16
15
  - 2.5.0
17
16
  - 2.6.5
18
17
  - 2.7.0
@@ -47,16 +46,6 @@ script:
47
46
 
48
47
  matrix:
49
48
  exclude:
50
- - rvm: 2.3.0
51
- gemfile: gemfiles/norails.gemfile
52
- - rvm: 2.3.0
53
- gemfile: gemfiles/rails_5.0.gemfile
54
- # - rvm: 2.3.0
55
- # gemfile: gemfiles/rails_5.0_nobrainer.gemfile
56
- - rvm: 2.3.0
57
- gemfile: gemfiles/rails_5.1.gemfile
58
- - rvm: 2.3.0
59
- gemfile: gemfiles/rails_5.2.gemfile
60
49
  - rvm: 2.7.0
61
50
  gemfile: gemfiles/rails_5.2.gemfile
62
51
  - rvm: 2.6.5
data/Appraisals CHANGED
@@ -8,7 +8,7 @@ appraise 'rails_4.2' do
8
8
  gem 'aws-sdk', '~> 2', platforms: :ruby
9
9
  gem 'redis-objects'
10
10
  gem 'activerecord-jdbcsqlite3-adapter', '1.3.24', platforms: :jruby
11
- gem "after_commit_everywhere", "~> 0.1", ">= 0.1.5"
11
+ gem "after_commit_everywhere", "~> 1.0"
12
12
  end
13
13
 
14
14
  appraise 'rails_4.2_nobrainer' do
@@ -21,7 +21,7 @@ appraise 'rails_4.2_mongoid_5' do
21
21
  gem 'rails', '4.2.5'
22
22
  gem 'mongoid', '~> 5.0'
23
23
  gem 'activerecord-jdbcsqlite3-adapter', '1.3.24', platforms: :jruby
24
- gem "after_commit_everywhere", "~> 0.1", ">= 0.1.5"
24
+ gem "after_commit_everywhere", "~> 1.0"
25
25
  end
26
26
 
27
27
  appraise 'rails_5.0' do
@@ -31,7 +31,7 @@ appraise 'rails_5.0' do
31
31
  gem 'dynamoid', '~> 1.3', platforms: :ruby
32
32
  gem 'aws-sdk', '~> 2', platforms: :ruby
33
33
  gem 'redis-objects'
34
- gem "after_commit_everywhere", "~> 0.1", ">= 0.1.5"
34
+ gem "after_commit_everywhere", "~> 1.0"
35
35
  end
36
36
 
37
37
  appraise 'rails_5.0_nobrainer' do
@@ -46,7 +46,7 @@ appraise 'rails_5.1' do
46
46
  gem 'dynamoid', '~> 1.3', platforms: :ruby
47
47
  gem 'aws-sdk', '~>2', platforms: :ruby
48
48
  gem 'redis-objects'
49
- gem "after_commit_everywhere", "~> 0.1", ">= 0.1.5"
49
+ gem "after_commit_everywhere", "~> 1.0"
50
50
  end
51
51
 
52
52
  appraise 'rails_5.2' do
@@ -56,7 +56,7 @@ appraise 'rails_5.2' do
56
56
  gem 'dynamoid', '~>2.2', platforms: :ruby
57
57
  gem 'aws-sdk', '~>2', platforms: :ruby
58
58
  gem 'redis-objects'
59
- gem "after_commit_everywhere", "~> 0.1", ">= 0.1.5"
59
+ gem "after_commit_everywhere", "~> 1.0"
60
60
  end
61
61
 
62
62
  appraise 'norails' do
data/CHANGELOG.md CHANGED
@@ -1,6 +1,23 @@
1
1
  # CHANGELOG
2
2
 
3
3
  ## unreleased
4
+ ## 5.2.0
5
+
6
+ * fix: timestamp will work with named machine [#739](https://github.com/aasm/aasm/pull/739), thanks to [RolandStuder](https://github.com/RolandStuder)
7
+ * Create namespaced scopes in PR [#735](https://github.com/aasm/aasm/pull/735), thanks to [caiohsramos](https://github.com/caiohsramos)
8
+ * Fix multiple state machines example per class on README in PR [#732](https://github.com/aasm/aasm/pull/732), thanks to [RodrigoVitiello](https://github.com/RodrigoVitiello)
9
+ * Update version in recommendation to add after_commit_everywhere in PR [#729](https://github.com/aasm/aasm/pull/729), thanks to [Envek](https://github.com/Envek)
10
+ * Fix i18n Event translations failing [#721](https://github.com/aasm/aasm/issues/721) in PR [#723](https://github.com/aasm/aasm/pull/723), thanks to [the-spectator](https://github.com/the-spectator)
11
+ * Add documentation to the Readme about how parameters are handled in AASM events in PR [#722](https://github.com/aasm/aasm/pull/722), thanks to [dstuebe](https://github.com/dstuebe)
12
+ * Fix human_state cached across locales [#709](https://github.com/aasm/aasm/issues/709) in PR [716](https://github.com/aasm/aasm/pull/716), thanks to [the-spectator](https://github.com/the-spectator)
13
+ * Relocate DslHelper from root namespace to under AASM namespace in PR [#711](https://github.com/aasm/aasm/pull/711) thank to [yujideveloper ](https://github.com/yujideveloper )
14
+ * Document how to define transitions from any state in in PR [#699](https://github.com/aasm/aasm/pull/699) thanks to [hedgesky](https://github.com/hedgesky)
15
+ * Add simple option for auto-generated timestamps in PR [#677](https://github.com/aasm/aasm/pull/677), thanks to [jaynetics](https://github.com/jaynetics)
16
+ ## 5.1.1
17
+
18
+ * Fix Depreciation message for after_commit_everywhere [#695](https://github.com/aasm/aasm/issues/695) in PR [#696](https://github.com/aasm/aasm/pull/696)
19
+ * Fix human_state to use display option [#684](https://github.com/aasm/aasm/issues/684) in PR [#697](https://github.com/aasm/aasm/pull/697)
20
+ * Remove support for ruby 2.3
4
21
 
5
22
  ## 5.1.0
6
23
 
data/README.md CHANGED
@@ -20,6 +20,7 @@
20
20
  - [Extending AASM](#extending-aasm)
21
21
  - [ActiveRecord](#activerecord)
22
22
  - [Bang events](#bang-events)
23
+ - [Timestamps](#timestamps)
23
24
  - [ActiveRecord enums](#activerecord-enums)
24
25
  - [Sequel](#sequel)
25
26
  - [Dynamoid](#dynamoid)
@@ -212,15 +213,28 @@ class LogRunTime
212
213
  end
213
214
  ```
214
215
 
215
- Also, you can pass parameters to events:
216
+ #### Parameters
217
+ You can pass parameters to events:
216
218
 
217
219
  ```ruby
218
220
  job = Job.new
219
221
  job.run(:defragmentation)
220
222
  ```
221
223
 
222
- In this case the `set_process` would be called with `:defragmentation` argument.
224
+ All guards and after callbacks will receive these parameters. In this case `set_process` would be called with
225
+ `:defragmentation` argument.
223
226
 
227
+ If the first argument to the event is a state (e.g. `:running` or `:finished`), the first argument is consumed and
228
+ the state machine will attempt to transition to that state. Add comma separated parameter for gaurds and callbacks
229
+
230
+ ```ruby
231
+ job = Job.new
232
+ job.run(:running, :defragmentation)
233
+ ```
234
+ In this case `set_process` won't be called, job will transition to running state and callback will receive
235
+ :defragmentation as parameter
236
+
237
+ #### Error Handling
224
238
  In case of an error during the event processing the error is rescued and passed to `:error`
225
239
  callback, which can handle it or re-raise it for further propagation.
226
240
 
@@ -434,6 +448,33 @@ job.stage1_completed
434
448
  job.aasm.current_state # stage3
435
449
  ```
436
450
 
451
+ You can define transition from any defined state by omitting `from`:
452
+
453
+ ```ruby
454
+ event :abort do
455
+ transitions to: :aborted
456
+ end
457
+ ```
458
+
459
+ ### Display name for state
460
+
461
+ You can define display name for state using :display option
462
+
463
+ ```ruby
464
+ class Job
465
+ include AASM
466
+
467
+ aasm do
468
+ state :stage1, initial: true, display: 'First Stage'
469
+ state :stage2
470
+ state :stage3
471
+ end
472
+ end
473
+
474
+ job = Job.new
475
+ job.aasm.human_state
476
+
477
+ ```
437
478
 
438
479
  ### Multiple state machines per class
439
480
 
@@ -476,13 +517,13 @@ simple = SimpleMultipleExample.new
476
517
 
477
518
  simple.aasm(:move).current_state
478
519
  # => :standing
479
- simple.aasm(:work).current
520
+ simple.aasm(:work).current_state
480
521
  # => :sleeping
481
522
 
482
523
  simple.start
483
524
  simple.aasm(:move).current_state
484
525
  # => :standing
485
- simple.aasm(:work).current
526
+ simple.aasm(:work).current_state
486
527
  # => :processing
487
528
 
488
529
  ```
@@ -679,7 +720,7 @@ end
679
720
  AASM comes with support for ActiveRecord and allows automatic persisting of the object's
680
721
  state in the database.
681
722
 
682
- Add `gem 'after_commit_everywhere', '~> 0.1', '>= 0.1.5'` to your Gemfile
723
+ Add `gem 'after_commit_everywhere', '~> 1.0'` to your Gemfile.
683
724
 
684
725
  ```ruby
685
726
  class Job < ActiveRecord::Base
@@ -781,6 +822,37 @@ job.aasm_state = :running # => raises AASM::NoDirectAssignmentError
781
822
  job.aasm_state # => 'sleeping'
782
823
  ```
783
824
 
825
+ ### Timestamps
826
+
827
+ You can tell _AASM_ to try to write a timestamp whenever a new state is entered.
828
+ If `timestamps: true` is set, _AASM_ will look for a field named like the new state plus `_at` and try to fill it:
829
+
830
+ ```ruby
831
+ class Job < ActiveRecord::Base
832
+ include AASM
833
+
834
+ aasm timestamps: true do
835
+ state :sleeping, initial: true
836
+ state :running
837
+
838
+ event :run do
839
+ transitions from: :sleeping, to: :running
840
+ end
841
+ end
842
+ end
843
+ ```
844
+
845
+ resulting in this:
846
+
847
+ ```ruby
848
+ job = Job.create
849
+ job.running_at # => nil
850
+ job.run!
851
+ job.running_at # => 2020-02-20 20:00:00
852
+ ```
853
+
854
+ Missing timestamp fields are silently ignored, so it is not necessary to have setters (such as ActiveRecord columns) for *all* states when using this option.
855
+
784
856
  #### ActiveRecord enums
785
857
 
786
858
  You can use
@@ -988,7 +1060,7 @@ job.save! #notify_about_running_job is not run
988
1060
  Please note that `:after_commit` AASM callbacks behaves around custom implementation
989
1061
  of transaction pattern rather than a real-life DB transaction. This fact still causes
990
1062
  the race conditions and redundant callback calls within nested transaction. In order
991
- to fix that it's highly recommended to add `gem 'after_commit_everywhere', '~> 0.1', '>= 0.1.5'`
1063
+ to fix that it's highly recommended to add `gem 'after_commit_everywhere', '~> 1.0'`
992
1064
  to your `Gemfile`.
993
1065
 
994
1066
  If you want to encapsulate state changes within an own transaction, the behavior
data/aasm.gemspec CHANGED
@@ -24,7 +24,7 @@ Gem::Specification.new do |s|
24
24
  s.add_development_dependency 'generator_spec'
25
25
  s.add_development_dependency 'appraisal'
26
26
  s.add_development_dependency "simplecov"
27
- s.add_development_dependency "codecov", ">= 0.1.17", '< 0.1.20'
27
+ s.add_development_dependency "codecov", ">= 0.1.21"
28
28
 
29
29
  # debugging
30
30
  # s.add_development_dependency 'debugger'
@@ -12,6 +12,6 @@ gem "dynamoid", "~> 1", platforms: :ruby
12
12
  gem "aws-sdk", "~> 2", platforms: :ruby
13
13
  gem "redis-objects"
14
14
  gem "activerecord-jdbcsqlite3-adapter", "1.3.24", platforms: :jruby
15
- gem "after_commit_everywhere", "~> 0.1", ">= 0.1.5"
15
+ gem "after_commit_everywhere", "~> 1.0"
16
16
 
17
17
  gemspec path: "../"
@@ -7,6 +7,6 @@ gem "rails", "4.2.5"
7
7
  gem "mime-types", "~> 2", platforms: [:ruby_19, :jruby]
8
8
  gem "mongoid", "~> 5.0"
9
9
  gem "activerecord-jdbcsqlite3-adapter", "1.3.24", platforms: :jruby
10
- gem "after_commit_everywhere", "~> 0.1", ">= 0.1.5"
10
+ gem "after_commit_everywhere", "~> 1.0"
11
11
 
12
12
  gemspec path: "../"
@@ -9,6 +9,6 @@ gem "sequel"
9
9
  gem "dynamoid", "~> 1.3", platforms: :ruby
10
10
  gem "aws-sdk", "~> 2", platforms: :ruby
11
11
  gem "redis-objects"
12
- gem "after_commit_everywhere", "~> 0.1", ">= 0.1.5"
12
+ gem "after_commit_everywhere", "~> 1.0"
13
13
 
14
14
  gemspec path: "../"
@@ -9,6 +9,6 @@ gem "sequel"
9
9
  gem "dynamoid", "~> 1.3", platforms: :ruby
10
10
  gem "aws-sdk", "~>2", platforms: :ruby
11
11
  gem "redis-objects"
12
- gem "after_commit_everywhere", "~> 0.1", ">= 0.1.5"
12
+ gem "after_commit_everywhere", "~> 1.0"
13
13
 
14
14
  gemspec path: "../"
@@ -9,6 +9,6 @@ gem "sequel"
9
9
  gem "dynamoid", "~>2.2", platforms: :ruby
10
10
  gem "aws-sdk", "~>2", platforms: :ruby
11
11
  gem "redis-objects"
12
- gem "after_commit_everywhere", "~> 0.1", ">= 0.1.5"
12
+ gem "after_commit_everywhere", "~> 1.0"
13
13
 
14
14
  gemspec path: "../"
data/lib/aasm/base.rb CHANGED
@@ -37,6 +37,9 @@ module AASM
37
37
  # string for a specific lock type i.e. FOR UPDATE NOWAIT
38
38
  configure :requires_lock, false
39
39
 
40
+ # automatically set `"#{state_name}_at" = ::Time.now` on state changes
41
+ configure :timestamps, false
42
+
40
43
  # set to true to forbid direct assignment of aasm_state column (in ActiveRecord)
41
44
  configure :no_direct_assignment, false
42
45
 
@@ -51,19 +54,12 @@ module AASM
51
54
  # Configure a logger, with default being a Logger to STDERR
52
55
  configure :logger, Logger.new(STDERR)
53
56
 
57
+ # setup timestamp-setting callback if enabled
58
+ setup_timestamps(@name)
59
+
54
60
  # make sure to raise an error if no_direct_assignment is enabled
55
61
  # and attribute is directly assigned though
56
- aasm_name = @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
- end
66
- end
62
+ setup_no_direct_assignment(@name)
67
63
  end
68
64
 
69
65
  # This method is both a getter and a setter
@@ -267,5 +263,28 @@ module AASM
267
263
  end
268
264
  end
269
265
 
266
+ def setup_timestamps(aasm_name)
267
+ return unless @state_machine.config.timestamps
268
+
269
+ after_all_transitions do
270
+ if self.class.aasm(:"#{aasm_name}").state_machine.config.timestamps
271
+ ts_setter = "#{aasm(aasm_name).to_state}_at="
272
+ respond_to?(ts_setter) && send(ts_setter, ::Time.now)
273
+ end
274
+ end
275
+ end
276
+
277
+ def setup_no_direct_assignment(aasm_name)
278
+ return unless @state_machine.config.no_direct_assignment
279
+
280
+ @klass.send(:define_method, "#{@state_machine.config.column}=") do |state_name|
281
+ if self.class.aasm(:"#{aasm_name}").state_machine.config.no_direct_assignment
282
+ raise AASM::NoDirectAssignmentError.new('direct assignment of AASM column has been disabled (see AASM configuration for this class)')
283
+ else
284
+ super(state_name)
285
+ end
286
+ end
287
+ end
288
+
270
289
  end
271
290
  end
@@ -24,6 +24,9 @@ module AASM
24
24
  # for ActiveRecord: use pessimistic locking
25
25
  attr_accessor :requires_lock
26
26
 
27
+ # automatically set `"#{state_name}_at" = ::Time.now` on state changes
28
+ attr_accessor :timestamps
29
+
27
30
  # forbid direct assignment in aasm_state column (in ActiveRecord)
28
31
  attr_accessor :no_direct_assignment
29
32
 
@@ -2,9 +2,9 @@
2
2
 
3
3
  module AASM::Core
4
4
  class Event
5
- include DslHelper
5
+ include AASM::DslHelper
6
6
 
7
- attr_reader :name, :state_machine, :options
7
+ attr_reader :name, :state_machine, :options, :default_display_name
8
8
 
9
9
  def initialize(name, state_machine, options = {}, &block)
10
10
  @name = name
@@ -13,6 +13,7 @@ module AASM::Core
13
13
  @valid_transitions = {}
14
14
  @guards = Array(options[:guard] || options[:guards] || options[:if])
15
15
  @unless = Array(options[:unless]) #TODO: This could use a better name
16
+ @default_display_name = name.to_s.gsub(/_/, ' ').capitalize
16
17
 
17
18
  # from aasm4
18
19
  @options = options # QUESTION: .dup ?
@@ -109,6 +110,10 @@ module AASM::Core
109
110
  transitions.flat_map(&:failures)
110
111
  end
111
112
 
113
+ def to_s
114
+ name.to_s
115
+ end
116
+
112
117
  private
113
118
 
114
119
  def attach_event_guards(definitions)
@@ -2,12 +2,13 @@
2
2
 
3
3
  module AASM::Core
4
4
  class State
5
- attr_reader :name, :state_machine, :options
5
+ attr_reader :name, :state_machine, :options, :default_display_name
6
6
 
7
7
  def initialize(name, klass, state_machine, options={})
8
8
  @name = name
9
9
  @klass = klass
10
10
  @state_machine = state_machine
11
+ @default_display_name = name.to_s.gsub(/_/, ' ').capitalize
11
12
  update(options)
12
13
  end
13
14
 
@@ -54,11 +55,11 @@ module AASM::Core
54
55
  end
55
56
 
56
57
  def display_name
57
- @display_name ||= begin
58
+ @display_name = begin
58
59
  if Module.const_defined?(:I18n)
59
60
  localized_name
60
61
  else
61
- name.to_s.gsub(/_/, ' ').capitalize
62
+ @default_display_name
62
63
  end
63
64
  end
64
65
  end
@@ -75,8 +76,8 @@ module AASM::Core
75
76
  private
76
77
 
77
78
  def update(options = {})
78
- if options.key?(:display) then
79
- @display_name = options.delete(:display)
79
+ if options.key?(:display)
80
+ @default_display_name = options.delete(:display)
80
81
  end
81
82
  @options = options
82
83
  self
@@ -2,7 +2,7 @@
2
2
 
3
3
  module AASM::Core
4
4
  class Transition
5
- include DslHelper
5
+ include AASM::DslHelper
6
6
 
7
7
  attr_reader :from, :to, :event, :opts, :failures
8
8
  alias_method :options, :opts
@@ -1,30 +1,32 @@
1
- module DslHelper
1
+ module AASM
2
+ module DslHelper
2
3
 
3
- class Proxy
4
- attr_accessor :options
4
+ class Proxy
5
+ attr_accessor :options
5
6
 
6
- def initialize(options, valid_keys, source)
7
- @valid_keys = valid_keys
8
- @source = source
7
+ def initialize(options, valid_keys, source)
8
+ @valid_keys = valid_keys
9
+ @source = source
9
10
 
10
- @options = options
11
- end
11
+ @options = options
12
+ end
12
13
 
13
- def method_missing(name, *args, &block)
14
- if @valid_keys.include?(name)
15
- options[name] = Array(options[name])
16
- options[name] << block if block
17
- options[name] += Array(args)
18
- else
19
- @source.send name, *args, &block
14
+ def method_missing(name, *args, &block)
15
+ if @valid_keys.include?(name)
16
+ options[name] = Array(options[name])
17
+ options[name] << block if block
18
+ options[name] += Array(args)
19
+ else
20
+ @source.send name, *args, &block
21
+ end
20
22
  end
21
23
  end
22
- end
23
24
 
24
- def add_options_from_dsl(options, valid_keys, &block)
25
- proxy = Proxy.new(options, valid_keys, self)
26
- proxy.instance_eval(&block)
27
- proxy.options
28
- end
25
+ def add_options_from_dsl(options, valid_keys, &block)
26
+ proxy = Proxy.new(options, valid_keys, self)
27
+ proxy.instance_eval(&block)
28
+ proxy.options
29
+ end
29
30
 
30
- end
31
+ end
32
+ end
@@ -28,7 +28,7 @@ module AASM
28
28
  end
29
29
 
30
30
  def human_state
31
- AASM::Localizer.new.human_state_name(@instance.class, state_object_for_name(current_state))
31
+ state_object_for_name(current_state).display_name
32
32
  end
33
33
 
34
34
  def states(options={}, *args)
@@ -5,7 +5,7 @@ module AASM
5
5
  list << :"#{i18n_scope(klass)}.events.#{i18n_klass(ancestor)}.#{event}"
6
6
  list
7
7
  end
8
- translate_queue(checklist) || I18n.translate(checklist.shift, :default => event.to_s.humanize)
8
+ translate_queue(checklist) || I18n.translate(checklist.shift, :default => default_display_name(event))
9
9
  end
10
10
 
11
11
  def human_state_name(klass, state)
@@ -14,7 +14,7 @@ module AASM
14
14
  list << item_for(klass, state, ancestor, :old_style => true)
15
15
  list
16
16
  end
17
- translate_queue(checklist) || I18n.translate(checklist.shift, :default => state.to_s.humanize)
17
+ translate_queue(checklist) || I18n.translate(checklist.shift, :default => default_display_name(state))
18
18
  end
19
19
 
20
20
  private
@@ -46,8 +46,18 @@ module AASM
46
46
  end
47
47
 
48
48
  def ancestors_list(klass)
49
+ has_active_record_base = defined?(::ActiveRecord::Base)
49
50
  klass.ancestors.select do |ancestor|
50
- ancestor.respond_to?(:model_name) unless ancestor.name == 'ActiveRecord::Base'
51
+ not_active_record_base = has_active_record_base ? (ancestor != ::ActiveRecord::Base) : true
52
+ ancestor.respond_to?(:model_name) && not_active_record_base
53
+ end
54
+ end
55
+
56
+ def default_display_name(object) # Can use better arguement name
57
+ if object.respond_to?(:default_display_name)
58
+ object.default_display_name
59
+ else
60
+ object.to_s.gsub(/_/, ' ').capitalize
51
61
  end
52
62
  end
53
63
  end
@@ -28,19 +28,6 @@ module AASM
28
28
  # end
29
29
  #
30
30
  def self.included(base)
31
- begin
32
- require 'after_commit_everywhere'
33
- raise LoadError unless Gem::Version.new(::AfterCommitEverywhere::VERSION) >= Gem::Version.new('0.1.5')
34
-
35
- base.send(:include, ::AfterCommitEverywhere) unless base.include?(::AfterCommitEverywhere)
36
- base.send(:alias_method, :aasm_execute_after_commit, :after_commit)
37
- rescue LoadError
38
- warn <<-MSG
39
- [DEPRECATION] :after_commit AASM callback is not safe in terms of race conditions and redundant calls.
40
- Please add `gem 'after_commit_everywhere', '~> 0.1', '>= 0.1.5'` to your Gemfile in order to fix that.
41
- MSG
42
- end
43
-
44
31
  base.send(:include, AASM::Persistence::Base)
45
32
  base.send(:include, AASM::Persistence::ORM)
46
33
  base.send(:include, AASM::Persistence::ActiveRecordPersistence::InstanceMethods)
@@ -74,6 +61,24 @@ module AASM
74
61
 
75
62
  private
76
63
 
64
+ def aasm_execute_after_commit
65
+ begin
66
+ require 'after_commit_everywhere'
67
+ raise LoadError unless Gem::Version.new(::AfterCommitEverywhere::VERSION) >= Gem::Version.new('0.1.5')
68
+
69
+ self.extend ::AfterCommitEverywhere
70
+ after_commit do
71
+ yield
72
+ end
73
+ rescue LoadError
74
+ warn <<-MSG
75
+ [DEPRECATION] :after_commit AASM callback is not safe in terms of race conditions and redundant calls.
76
+ Please add `gem 'after_commit_everywhere', '~> 1.0'` to your Gemfile in order to fix that.
77
+ MSG
78
+ yield
79
+ end
80
+ end
81
+
77
82
  def aasm_raise_invalid_record
78
83
  raise ActiveRecord::RecordInvalid.new(self)
79
84
  end
@@ -59,7 +59,9 @@ module AASM
59
59
  # make sure to create a (named) scope for each state
60
60
  def state_with_scope(*args)
61
61
  names = state_without_scope(*args)
62
- names.each { |name| create_scope(name) if create_scope?(name) }
62
+ names.each do |name|
63
+ create_scopes(name)
64
+ end
63
65
  end
64
66
  alias_method :state_without_scope, :state
65
67
  alias_method :state, :state_with_scope
@@ -71,7 +73,16 @@ module AASM
71
73
  end
72
74
 
73
75
  def create_scope(name)
74
- @klass.aasm_create_scope(@name, name)
76
+ @klass.aasm_create_scope(@name, name) if create_scope?(name)
77
+ end
78
+
79
+ def create_scopes(name)
80
+ if namespace?
81
+ # Create default scopes even when namespace? for backward compatibility
82
+ namepaced_name = "#{namespace}_#{name}"
83
+ create_scope(namepaced_name)
84
+ end
85
+ create_scope(name)
75
86
  end
76
87
  end # Base
77
88
 
@@ -135,7 +135,7 @@ module AASM
135
135
  super
136
136
  end
137
137
 
138
- if success
138
+ if success && !(event.options.keys & [:after_commit, :after_all_commits]).empty?
139
139
  aasm_execute_after_commit do
140
140
  event.fire_callbacks(:after_commit, self, *args)
141
141
  event.fire_global_callbacks(:after_all_commits, self, *args)
data/lib/aasm/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module AASM
2
- VERSION = "5.1.0"
2
+ VERSION = "5.2.0"
3
3
  end
data/lib/aasm.rb CHANGED
@@ -1,5 +1,3 @@
1
- require 'ostruct'
2
-
3
1
  require 'aasm/version'
4
2
  require 'aasm/errors'
5
3
  require 'aasm/configuration'