aasm 5.0.6 → 5.2.0

Sign up to get free protection for your applications and to get access to all the features.
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