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
data/spec/en.yml CHANGED
@@ -4,9 +4,6 @@ en:
4
4
  localizer_test_model:
5
5
  close: "Let's close it!"
6
6
 
7
- attributes:
8
- localizer_test_model:
9
- aasm_state/opened: "It's open now!"
10
7
  errors:
11
8
  messages:
12
9
  record_invalid: "Invalid record"
@@ -1,10 +1,13 @@
1
1
  en:
2
2
  activerecord:
3
- events:
3
+ attributes:
4
4
  localizer_test_model:
5
- close: "Let's close it!"
5
+ aasm_state:
6
+ opened: "It's open now!"
6
7
 
8
+ fr:
9
+ activerecord:
7
10
  attributes:
8
11
  localizer_test_model:
9
12
  aasm_state:
10
- opened: "It's open now!"
13
+ opened: "C'est ouvert maintenant!"
@@ -0,0 +1,11 @@
1
+ en:
2
+ activerecord:
3
+ attributes:
4
+ localizer_test_model:
5
+ aasm_state/opened: "It's open now!"
6
+
7
+ fr:
8
+ activerecord:
9
+ attributes:
10
+ localizer_test_model:
11
+ aasm_state/opened: "C'est ouvert maintenant!"
@@ -0,0 +1,93 @@
1
+ class ActiveRecordCallback < ActiveRecord::Base
2
+ include AASM
3
+
4
+ def reset_data
5
+ @data = []
6
+ end
7
+
8
+ def data
9
+ @data.join(' ')
10
+ end
11
+
12
+ aasm column: :status do
13
+ before_all_events :before_all_events
14
+ after_all_events :after_all_events
15
+ ensure_on_all_events :ensure_on_all_events
16
+ after_all_transitions :after_all_transitions
17
+
18
+ state :open, :initial => true,
19
+ :before_enter => :before_enter_open,
20
+ :enter => :enter_open,
21
+ :after_enter => :after_enter_open,
22
+ :before_exit => :before_exit_open,
23
+ :exit => :exit_open,
24
+ :after_exit => :after_exit_open
25
+
26
+ state :closed,
27
+ :before_enter => :before_enter_closed,
28
+ :enter => :enter_closed,
29
+ :after_enter => :after_enter_closed,
30
+ :before_exit => :before_exit_closed,
31
+ :exit => :exit_closed,
32
+ :after_exit => :after_exit_closed
33
+
34
+ event :close,
35
+ :before => :before_event,
36
+ :after => :after_event,
37
+ :guard => :event_guard,
38
+ :before_success => :event_before_success,
39
+ :after_commit => :event_after_commit,
40
+ :ensure => :ensure_event do
41
+ transitions :to => :closed, :from => [:open],
42
+ :guard => :transition_guard,
43
+ :after => :after_transition,
44
+ :success => :success_transition
45
+ end
46
+
47
+ event :open, :before => :before_event, :after => :after_event do
48
+ transitions :to => :open, :from => :closed
49
+ end
50
+ end
51
+
52
+ def log(text)
53
+ @data ||= []
54
+ @data << text
55
+ #puts text
56
+ end
57
+
58
+ def aasm_write_state(*args); log('aasm_write_state'); true; end
59
+ def before_enter_open; log('before_enter_open'); end
60
+ def enter_open; log('enter_open'); end
61
+ def before_exit_open; log('before_exit_open'); end
62
+ def after_enter_open; log('after_enter_open'); end
63
+ def exit_open; log('exit_open'); end
64
+ def after_exit_open; log('after_exit_open'); end
65
+
66
+ def before_enter_closed; log('before_enter_closed'); end
67
+ def enter_closed; log('enter_closed'); end
68
+ def before_exit_closed; log('before_exit_closed'); end
69
+ def exit_closed; log('exit_closed'); end
70
+ def after_enter_closed; log('after_enter_closed'); end
71
+ def after_exit_closed; log('after_exit_closed'); end
72
+
73
+ def event_guard; log('event_guard'); !@fail_event_guard; end
74
+ def transition_guard; log('transition_guard'); !@fail_transition_guard; end
75
+
76
+ def event_before_success; log('event_before_success'); end
77
+
78
+ def after_transition; log('after_transition'); end
79
+ def after_all_transitions; log('after_all_transitions'); end
80
+
81
+ def before_all_events; log('before_all_events') end
82
+ def before_event; log('before_event'); end
83
+ def after_event; log('after_event'); end
84
+ def after_all_events; log('after_all_events'); end
85
+
86
+ def after_transition; log('after_transition'); end
87
+ def success_transition; log('transition_success'); end
88
+
89
+ def ensure_event; log('ensure'); end
90
+ def ensure_on_all_events; log('ensure'); end
91
+
92
+ def event_after_commit; log('after_commit'); end
93
+ end
@@ -11,24 +11,32 @@ end
11
11
 
12
12
  describe 'localized state names' do
13
13
  before(:all) do
14
- I18n.load_path << 'spec/en.yml'
15
- I18n.default_locale = :en
14
+ I18n.load_path << 'spec/localizer_test_model_new_style.yml'
16
15
  I18n.reload!
17
16
  end
18
17
 
19
18
  after(:all) do
20
- I18n.load_path.clear
19
+ I18n.load_path.delete('spec/localizer_test_model_new_style.yml')
20
+ I18n.backend.load_translations
21
21
  end
22
22
 
23
23
  it 'should localize' do
24
24
  state = LocalizerTestModel.aasm.states.detect {|s| s == :opened}
25
25
  expect(state.localized_name).to eq("It's open now!")
26
26
  expect(state.human_name).to eq("It's open now!")
27
+ expect(state.display_name).to eq("It's open now!")
28
+
29
+ I18n.with_locale(:fr) do
30
+ expect(state.localized_name).to eq("C'est ouvert maintenant!")
31
+ expect(state.human_name).to eq("C'est ouvert maintenant!")
32
+ expect(state.display_name).to eq("C'est ouvert maintenant!")
33
+ end
27
34
  end
28
35
 
29
36
  it 'should use fallback' do
30
37
  state = LocalizerTestModel.aasm.states.detect {|s| s == :closed}
31
38
  expect(state.localized_name).to eq('Closed')
32
39
  expect(state.human_name).to eq('Closed')
40
+ expect(state.display_name).to eq('Closed')
33
41
  end
34
42
  end
@@ -0,0 +1,16 @@
1
+ class MultipleNamespaced < ActiveRecord::Base
2
+ include AASM
3
+
4
+ aasm(:status, namespace: :car) do
5
+ state :unsold, initial: true
6
+ state :sold
7
+
8
+ event :sell do
9
+ transitions from: :unsold, to: :sold
10
+ end
11
+
12
+ event :return do
13
+ transitions from: :sold, to: :unsold
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ class TimestampExample < ActiveRecord::Base
2
+ include AASM
3
+
4
+ aasm column: :aasm_state, timestamps: true do
5
+ state :opened
6
+ state :closed
7
+
8
+ event :open do
9
+ transitions to: :opened
10
+ end
11
+
12
+ event :close do
13
+ transitions to: :closed
14
+ end
15
+ end
16
+ end
@@ -2,7 +2,7 @@ class DefaultState
2
2
  attr_accessor :transient_store, :persisted_store
3
3
  include AASM
4
4
  aasm do
5
- state :alpha, :initial => true
5
+ state :alpha, :initial => true, display: 'ALPHA'
6
6
  state :beta
7
7
  state :gamma
8
8
  event :release do
@@ -0,0 +1,20 @@
1
+ class TimestampExampleMongoid
2
+ include Mongoid::Document
3
+ include AASM
4
+
5
+ field :status, type: String
6
+ field :opened_at, type: Time
7
+
8
+ aasm column: :status, timestamps: true do
9
+ state :opened
10
+ state :closed
11
+
12
+ event :open do
13
+ transitions to: :opened
14
+ end
15
+
16
+ event :close do
17
+ transitions to: :closed
18
+ end
19
+ end
20
+ 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
@@ -0,0 +1,19 @@
1
+ class TimestampsExample
2
+ include AASM
3
+
4
+ attr_accessor :opened_at
5
+ attr_reader :closed_at
6
+
7
+ aasm timestamps: true do
8
+ state :opened
9
+ state :closed
10
+
11
+ event :open do
12
+ transitions to: :opened
13
+ end
14
+
15
+ event :close do
16
+ transitions to: :closed
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,13 @@
1
+ class TimestampsWithNamedMachineExample
2
+ include AASM
3
+
4
+ attr_accessor :opened_at
5
+
6
+ aasm :my_state, timestamps: true do
7
+ state :opened
8
+
9
+ event :open do
10
+ transitions to: :opened
11
+ end
12
+ end
13
+ end
data/spec/spec_helper.rb CHANGED
@@ -13,6 +13,7 @@ $LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib
13
13
  require 'aasm'
14
14
  require 'rspec'
15
15
  require 'aasm/rspec'
16
+ require 'i18n'
16
17
  require 'pry'
17
18
 
18
19
  # require 'ruby-debug'; Debugger.settings[:autoeval] = true; debugger; rubys_debugger = 'annoying'
@@ -34,3 +35,7 @@ Dir[File.dirname(__FILE__) + "/spec_helpers/**/*.rb"].sort.each { |f| require Fi
34
35
 
35
36
  # example model classes
36
37
  Dir[File.dirname(__FILE__) + "/models/*.rb"].sort.each { |f| require File.expand_path(f) }
38
+
39
+ I18n.load_path << 'spec/en.yml'
40
+ I18n.enforce_available_locales = false
41
+ I18n.default_locale = :en
@@ -13,6 +13,10 @@ if defined?(ActiveRecord)
13
13
  expect(DefaultState.new.aasm.current_state).to eql :alpha
14
14
  end
15
15
 
16
+ it "uses display option" do
17
+ expect(DefaultState.new.aasm.human_state).to eql "ALPHA"
18
+ end
19
+
16
20
  it "uses the provided method" do
17
21
  expect(ProvidedState.new.aasm.current_state).to eql :beta
18
22
  end
@@ -166,11 +166,15 @@ describe "special cases" do
166
166
  end
167
167
 
168
168
  describe 'aasm.states_for_select' do
169
- it "should return a select friendly array of states" do
170
- expect(FooMultiple.aasm(:left)).to respond_to(:states_for_select)
171
- expect(FooMultiple.aasm(:left).states_for_select).to eq(
172
- [['Open', 'open'], ['Closed', 'closed'], ['Final', 'final']]
173
- )
169
+ context 'without I18n' do
170
+ before { allow(Module).to receive(:const_defined?).with(:I18n).and_return(nil) }
171
+
172
+ it "should return a select friendly array of states" do
173
+ expect(FooMultiple.aasm(:left)).to respond_to(:states_for_select)
174
+ expect(FooMultiple.aasm(:left).states_for_select).to eq(
175
+ [['Open', 'open'], ['Closed', 'closed'], ['Final', 'final']]
176
+ )
177
+ end
174
178
  end
175
179
  end
176
180
 
@@ -102,9 +102,13 @@ describe "special cases" do
102
102
  end
103
103
 
104
104
  describe 'aasm.states_for_select' do
105
- it "should return a select friendly array of states" do
106
- expect(Foo.aasm).to respond_to(:states_for_select)
107
- expect(Foo.aasm.states_for_select).to eq([['Open', 'open'], ['Closed', 'closed'], ['Final', 'final']])
105
+ context 'without I18n' do
106
+ before { allow(Module).to receive(:const_defined?).with(:I18n).and_return(nil) }
107
+
108
+ it "should return a select friendly array of states" do
109
+ expect(Foo.aasm).to respond_to(:states_for_select)
110
+ expect(Foo.aasm.states_for_select).to eq([['Open', 'open'], ['Closed', 'closed'], ['Final', 'final']])
111
+ end
108
112
  end
109
113
  end
110
114
 
@@ -1,20 +1,18 @@
1
1
  require 'spec_helper'
2
2
 
3
- if defined?(ActiceRecord)
4
- require 'i18n'
5
-
6
- I18n.enforce_available_locales = false
3
+ if defined?(ActiveRecord)
4
+ require 'models/active_record/localizer_test_model'
7
5
  load_schema
8
6
 
9
7
  describe AASM::Localizer, "new style" do
10
8
  before(:all) do
11
- I18n.load_path << 'spec/en.yml'
12
- I18n.default_locale = :en
9
+ I18n.load_path << 'spec/localizer_test_model_new_style.yml'
13
10
  I18n.reload!
14
11
  end
15
12
 
16
13
  after(:all) do
17
- I18n.load_path.clear
14
+ I18n.load_path.delete('spec/localizer_test_model_new_style.yml')
15
+ I18n.backend.load_translations
18
16
  end
19
17
 
20
18
  let (:foo_opened) { LocalizerTestModel.new }
@@ -31,25 +29,42 @@ if defined?(ActiceRecord)
31
29
  end
32
30
 
33
31
  context 'aasm.human_event_name' do
34
- it 'should return translated event name' do
35
- expect(LocalizerTestModel.aasm.human_event_name(:close)).to eq("Let's close it!")
32
+ context 'with event name' do
33
+ it 'should return translated event name' do
34
+ expect(LocalizerTestModel.aasm.human_event_name(:close)).to eq("Let's close it!")
35
+ end
36
+
37
+ it 'should return humanized event name' do
38
+ expect(LocalizerTestModel.aasm.human_event_name(:open)).to eq("Open")
39
+ end
36
40
  end
37
41
 
38
- it 'should return humanized event name' do
39
- expect(LocalizerTestModel.aasm.human_event_name(:open)).to eq("Open")
42
+ context 'with event object' do
43
+ it 'should return translated event name' do
44
+ event = LocalizerTestModel.aasm.events.detect { |e| e.name == :close }
45
+
46
+ expect(LocalizerTestModel.aasm.human_event_name(event)).to eq("Let's close it!")
47
+ end
48
+
49
+ it 'should return humanized event name' do
50
+ event = LocalizerTestModel.aasm.events.detect { |e| e.name == :open }
51
+
52
+ expect(LocalizerTestModel.aasm.human_event_name(event)).to eq("Open")
53
+ end
40
54
  end
41
55
  end
42
56
  end
43
57
 
44
58
  describe AASM::Localizer, "deprecated style" do
45
59
  before(:all) do
46
- I18n.load_path << 'spec/en_deprecated_style.yml'
47
- I18n.default_locale = :en
60
+ I18n.load_path << 'spec/localizer_test_model_deprecated_style.yml'
48
61
  I18n.reload!
62
+ I18n.backend.load_translations
49
63
  end
50
64
 
51
65
  after(:all) do
52
- I18n.load_path.clear
66
+ I18n.load_path.delete('spec/localizer_test_model_deprecated_style.yml')
67
+ I18n.backend.load_translations
53
68
  end
54
69
 
55
70
  let (:foo_opened) { LocalizerTestModel.new }
@@ -66,12 +81,28 @@ if defined?(ActiceRecord)
66
81
  end
67
82
 
68
83
  context 'aasm.human_event_name' do
69
- it 'should return translated event name' do
70
- expect(LocalizerTestModel.aasm.human_event_name(:close)).to eq("Let's close it!")
84
+ context 'with event name' do
85
+ it 'should return translated event name' do
86
+ expect(LocalizerTestModel.aasm.human_event_name(:close)).to eq("Let's close it!")
87
+ end
88
+
89
+ it 'should return humanized event name' do
90
+ expect(LocalizerTestModel.aasm.human_event_name(:open)).to eq("Open")
91
+ end
71
92
  end
72
93
 
73
- it 'should return humanized event name' do
74
- expect(LocalizerTestModel.aasm.human_event_name(:open)).to eq("Open")
94
+ context 'with event object' do
95
+ it 'should return translated event name' do
96
+ event = LocalizerTestModel.aasm.events.detect { |e| e.name == :close }
97
+
98
+ expect(LocalizerTestModel.aasm.human_event_name(event)).to eq("Let's close it!")
99
+ end
100
+
101
+ it 'should return humanized event name' do
102
+ event = LocalizerTestModel.aasm.events.detect { |e| e.name == :open }
103
+
104
+ expect(LocalizerTestModel.aasm.human_event_name(event)).to eq("Open")
105
+ end
75
106
  end
76
107
  end
77
108
  end