aasm 3.0.24 → 3.4.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 (59) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +6 -0
  3. data/.travis.yml +29 -4
  4. data/CHANGELOG.md +56 -0
  5. data/Gemfile +10 -1
  6. data/LICENSE +1 -1
  7. data/README.md +151 -20
  8. data/aasm.gemspec +5 -6
  9. data/gemfiles/rails_3.2.gemfile +13 -0
  10. data/gemfiles/rails_4.0.gemfile +16 -0
  11. data/gemfiles/rails_4.1.gemfile +16 -0
  12. data/lib/aasm/aasm.rb +36 -32
  13. data/lib/aasm/base.rb +49 -31
  14. data/lib/aasm/event.rb +28 -17
  15. data/lib/aasm/instance_base.rb +9 -4
  16. data/lib/aasm/localizer.rb +1 -1
  17. data/lib/aasm/persistence/active_record_persistence.rb +65 -16
  18. data/lib/aasm/persistence/base.rb +10 -14
  19. data/lib/aasm/persistence/mongoid_persistence.rb +10 -8
  20. data/lib/aasm/persistence/sequel_persistence.rb +108 -0
  21. data/lib/aasm/persistence.rb +3 -0
  22. data/lib/aasm/state.rb +4 -3
  23. data/lib/aasm/state_machine.rb +18 -10
  24. data/lib/aasm/transition.rb +13 -6
  25. data/lib/aasm/version.rb +1 -1
  26. data/lib/aasm.rb +0 -3
  27. data/spec/database.rb +33 -0
  28. data/spec/models/double_definer.rb +21 -0
  29. data/spec/models/foo.rb +2 -1
  30. data/spec/models/guardian.rb +48 -0
  31. data/spec/models/mongoid/no_scope_mongoid.rb +1 -1
  32. data/spec/models/mongoid/simple_mongoid.rb +5 -4
  33. data/spec/models/mongoid/simple_new_dsl_mongoid.rb +1 -1
  34. data/spec/models/not_auto_loaded/process.rb +10 -8
  35. data/spec/models/persistence.rb +5 -13
  36. data/spec/spec_helper.rb +1 -1
  37. data/spec/unit/api_spec.rb +12 -12
  38. data/spec/unit/callbacks_spec.rb +29 -45
  39. data/spec/unit/complex_example_spec.rb +24 -15
  40. data/spec/unit/event_naming_spec.rb +24 -0
  41. data/spec/unit/event_spec.rb +124 -76
  42. data/spec/unit/guard_spec.rb +60 -0
  43. data/spec/unit/initial_state_spec.rb +4 -5
  44. data/spec/unit/inspection_spec.rb +42 -53
  45. data/spec/unit/localizer_spec.rb +22 -18
  46. data/spec/unit/memory_leak_spec.rb +2 -2
  47. data/spec/unit/new_dsl_spec.rb +2 -2
  48. data/spec/unit/persistence/active_record_persistence_spec.rb +357 -89
  49. data/spec/unit/persistence/mongoid_persistance_spec.rb +102 -81
  50. data/spec/unit/persistence/sequel_persistence_spec.rb +103 -0
  51. data/spec/unit/reloading_spec.rb +15 -0
  52. data/spec/unit/simple_example_spec.rb +20 -21
  53. data/spec/unit/state_spec.rb +16 -16
  54. data/spec/unit/subclassing_spec.rb +8 -8
  55. data/spec/unit/transition_spec.rb +59 -44
  56. metadata +38 -96
  57. data/lib/aasm/deprecated/aasm.rb +0 -15
  58. data/spec/models/callback_old_dsl.rb +0 -41
  59. data/spec/schema.rb +0 -35
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+
3
+ describe "per-transition guards" do
4
+ let(:guardian) { Guardian.new }
5
+
6
+ it "allows the transition if the guard succeeds" do
7
+ expect { guardian.use_one_guard_that_succeeds! }.to_not raise_error
8
+ expect(guardian).to be_beta
9
+ end
10
+
11
+ it "stops the transition if the guard fails" do
12
+ expect { guardian.use_one_guard_that_fails! }.to raise_error(AASM::InvalidTransition)
13
+ expect(guardian).to be_alpha
14
+ end
15
+
16
+ it "allows the transition if all guards succeeds" do
17
+ expect { guardian.use_guards_that_succeed! }.to_not raise_error
18
+ expect(guardian).to be_beta
19
+ end
20
+
21
+ it "stops the transition if the first guard fails" do
22
+ expect { guardian.use_guards_where_the_first_fails! }.to raise_error(AASM::InvalidTransition)
23
+ expect(guardian).to be_alpha
24
+ end
25
+
26
+ it "stops the transition if the second guard fails" do
27
+ expect { guardian.use_guards_where_the_second_fails! }.to raise_error(AASM::InvalidTransition)
28
+ expect(guardian).to be_alpha
29
+ end
30
+ end
31
+
32
+ describe "event guards" do
33
+ let(:guardian) { Guardian.new }
34
+
35
+ it "allows the transition if the event guards succeed" do
36
+ expect { guardian.use_event_guards_that_succeed! }.to_not raise_error
37
+ expect(guardian).to be_beta
38
+ end
39
+
40
+ it "allows the transition if the event and transition guards succeed" do
41
+ expect { guardian.use_event_and_transition_guards_that_succeed! }.to_not raise_error
42
+ expect(guardian).to be_beta
43
+ end
44
+
45
+ it "stops the transition if the first event guard fails" do
46
+ expect { guardian.use_event_guards_where_the_first_fails! }.to raise_error(AASM::InvalidTransition)
47
+ expect(guardian).to be_alpha
48
+ end
49
+
50
+ it "stops the transition if the second event guard fails" do
51
+ expect { guardian.use_event_guards_where_the_second_fails! }.to raise_error(AASM::InvalidTransition)
52
+ expect(guardian).to be_alpha
53
+ end
54
+
55
+ it "stops the transition if the transition guard fails" do
56
+ expect { guardian.use_event_and_transition_guards_where_third_fails! }.to raise_error(AASM::InvalidTransition)
57
+ expect(guardian).to be_alpha
58
+ end
59
+
60
+ end
@@ -5,8 +5,8 @@ class Banker
5
5
  aasm do
6
6
  state :retired
7
7
  state :selling_bad_mortgages
8
+ initial_state Proc.new { |banker| banker.rich? ? :retired : :selling_bad_mortgages }
8
9
  end
9
- aasm_initial_state Proc.new { |banker| banker.rich? ? :retired : :selling_bad_mortgages }
10
10
  RICH = 1_000_000
11
11
  attr_accessor :balance
12
12
  def initialize(balance = 0); self.balance = balance; end
@@ -17,12 +17,11 @@ describe 'initial states' do
17
17
  let(:bar) {Bar.new}
18
18
 
19
19
  it 'should use the first state defined if no initial state is given' do
20
- bar.aasm_current_state.should == :read
21
- # bar.aasm.current_state.should == :read # not yet supported
20
+ expect(bar.aasm.current_state).to eq(:read)
22
21
  end
23
22
 
24
23
  it 'should determine initial state from the Proc results' do
25
- Banker.new(Banker::RICH - 1).aasm_current_state.should == :selling_bad_mortgages
26
- Banker.new(Banker::RICH + 1).aasm_current_state.should == :retired
24
+ expect(Banker.new(Banker::RICH - 1).aasm.current_state).to eq(:selling_bad_mortgages)
25
+ expect(Banker.new(Banker::RICH + 1).aasm.current_state).to eq(:retired)
27
26
  end
28
27
  end
@@ -1,30 +1,17 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe 'inspection for common cases' do
4
- it 'should support the old DSL' do
5
- Foo.should respond_to(:aasm_states)
6
- Foo.aasm_states.should include(:open)
7
- Foo.aasm_states.should include(:closed)
8
-
9
- Foo.should respond_to(:aasm_initial_state)
10
- Foo.aasm_initial_state.should == :open
11
-
12
- Foo.should respond_to(:aasm_events)
13
- Foo.aasm_events.should include(:close)
14
- Foo.aasm_events.should include(:null)
15
- end
16
-
17
4
  it 'should support the new DSL' do
18
- Foo.aasm.should respond_to(:states)
19
- Foo.aasm.states.should include(:open)
20
- Foo.aasm.states.should include(:closed)
5
+ expect(Foo.aasm).to respond_to(:states)
6
+ expect(Foo.aasm.states).to include(:open)
7
+ expect(Foo.aasm.states).to include(:closed)
21
8
 
22
- Foo.aasm.should respond_to(:initial_state)
23
- Foo.aasm.initial_state.should == :open
9
+ expect(Foo.aasm).to respond_to(:initial_state)
10
+ expect(Foo.aasm.initial_state).to eq(:open)
24
11
 
25
- Foo.aasm.should respond_to(:events)
26
- Foo.aasm.events.should include(:close)
27
- Foo.aasm.events.should include(:null)
12
+ expect(Foo.aasm).to respond_to(:events)
13
+ expect(Foo.aasm.events).to include(:close)
14
+ expect(Foo.aasm.events).to include(:null)
28
15
  end
29
16
 
30
17
  context "instance level inspection" do
@@ -33,77 +20,79 @@ describe 'inspection for common cases' do
33
20
 
34
21
  it "delivers all states" do
35
22
  states = foo.aasm.states
36
- states.should include(:open)
37
- states.should include(:closed)
23
+ expect(states).to include(:open)
24
+ expect(states).to include(:closed)
25
+ expect(states).to include(:final)
38
26
 
39
27
  states = foo.aasm.states(:permissible => true)
40
- states.should include(:closed)
41
- states.should_not include(:open)
28
+ expect(states).to include(:closed)
29
+ expect(states).not_to include(:open)
30
+ expect(states).not_to include(:final)
42
31
 
43
32
  foo.close
44
- foo.aasm.states(:permissible => true).should be_empty
33
+ expect(foo.aasm.states(:permissible => true)).to be_empty
45
34
  end
46
35
 
47
36
  it "delivers all states for subclasses" do
48
37
  states = two.aasm.states
49
- states.should include(:open)
50
- states.should include(:closed)
51
- states.should include(:foo)
38
+ expect(states).to include(:open)
39
+ expect(states).to include(:closed)
40
+ expect(states).to include(:foo)
52
41
 
53
42
  states = two.aasm.states(:permissible => true)
54
- states.should include(:closed)
55
- states.should_not include(:open)
43
+ expect(states).to include(:closed)
44
+ expect(states).not_to include(:open)
56
45
 
57
46
  two.close
58
- two.aasm.states(:permissible => true).should be_empty
47
+ expect(two.aasm.states(:permissible => true)).to be_empty
59
48
  end
60
49
 
61
50
  it "delivers all events" do
62
51
  events = foo.aasm.events
63
- events.should include(:close)
64
- events.should include(:null)
52
+ expect(events).to include(:close)
53
+ expect(events).to include(:null)
65
54
  foo.close
66
- foo.aasm.events.should be_empty
55
+ expect(foo.aasm.events).to be_empty
67
56
  end
68
57
  end
69
58
 
70
59
  it 'should list states in the order they have been defined' do
71
- Conversation.aasm.states.should == [:needs_attention, :read, :closed, :awaiting_response, :junk]
60
+ expect(Conversation.aasm.states).to eq([:needs_attention, :read, :closed, :awaiting_response, :junk])
72
61
  end
73
62
  end
74
63
 
75
64
  describe "special cases" do
76
65
  it "should support valid a state name" do
77
- Argument.aasm_states.should include(:invalid)
78
- Argument.aasm_states.should include(:valid)
66
+ expect(Argument.aasm.states).to include(:invalid)
67
+ expect(Argument.aasm.states).to include(:valid)
79
68
 
80
69
  argument = Argument.new
81
- argument.invalid?.should be_true
82
- argument.aasm_current_state.should == :invalid
70
+ expect(argument.invalid?).to be_true
71
+ expect(argument.aasm.current_state).to eq(:invalid)
83
72
 
84
73
  argument.valid!
85
- argument.valid?.should be_true
86
- argument.aasm_current_state.should == :valid
74
+ expect(argument.valid?).to be_true
75
+ expect(argument.aasm.current_state).to eq(:valid)
87
76
  end
88
77
  end
89
78
 
90
- describe :aasm_states_for_select do
79
+ describe 'aasm.states_for_select' do
91
80
  it "should return a select friendly array of states" do
92
- Foo.should respond_to(:aasm_states_for_select)
93
- Foo.aasm_states_for_select.should == [['Open', 'open'], ['Closed', 'closed']]
81
+ expect(Foo.aasm).to respond_to(:states_for_select)
82
+ expect(Foo.aasm.states_for_select).to eq([['Open', 'open'], ['Closed', 'closed'], ['Final', 'final']])
94
83
  end
95
84
  end
96
85
 
97
- describe :aasm_from_states_for_state do
86
+ describe 'aasm.from_states_for_state' do
98
87
  it "should return all from states for a state" do
99
- AuthMachine.should respond_to(:aasm_from_states_for_state)
100
- froms = AuthMachine.aasm_from_states_for_state(:active)
101
- [:pending, :passive, :suspended].each {|from| froms.should include(from)}
88
+ expect(AuthMachine.aasm).to respond_to(:from_states_for_state)
89
+ froms = AuthMachine.aasm.from_states_for_state(:active)
90
+ [:pending, :passive, :suspended].each {|from| expect(froms).to include(from)}
102
91
  end
103
92
 
104
93
  it "should return from states for a state for a particular transition only" do
105
- froms = AuthMachine.aasm_from_states_for_state(:active, :transition => :unsuspend)
106
- [:suspended].each {|from| froms.should include(from)}
94
+ froms = AuthMachine.aasm.from_states_for_state(:active, :transition => :unsuspend)
95
+ [:suspended].each {|from| expect(froms).to include(from)}
107
96
  end
108
97
  end
109
98
 
@@ -111,7 +100,7 @@ describe 'permissible events' do
111
100
  let(:foo) {Foo.new}
112
101
 
113
102
  it 'work' do
114
- foo.aasm.permissible_events.should include(:close)
115
- foo.aasm.permissible_events.should_not include(:null)
103
+ expect(foo.aasm.permissible_events).to include(:close)
104
+ expect(foo.aasm.permissible_events).not_to include(:null)
116
105
  end
117
106
  end
@@ -10,12 +10,12 @@ class LocalizerTestModel < ActiveRecord::Base
10
10
 
11
11
  attr_accessor :aasm_state
12
12
 
13
- aasm_initial_state :opened
14
- aasm_state :opened
15
- aasm_state :closed
16
-
17
- aasm_event :close
18
- aasm_event :open
13
+ aasm do
14
+ state :opened, :initial => true
15
+ state :closed
16
+ event :close
17
+ event :open
18
+ end
19
19
  end
20
20
 
21
21
  describe 'localized state names' do
@@ -30,11 +30,15 @@ describe 'localized state names' do
30
30
  end
31
31
 
32
32
  it 'should localize' do
33
- LocalizerTestModel.aasm.states.detect {|s| s == :opened}.localized_name.should == "It's open now!"
33
+ state = LocalizerTestModel.aasm.states.detect {|s| s == :opened}
34
+ expect(state.localized_name).to eq("It's open now!")
35
+ expect(state.human_name).to eq("It's open now!")
34
36
  end
35
37
 
36
38
  it 'should use fallback' do
37
- LocalizerTestModel.aasm.states.detect {|s| s == :closed}.localized_name.should == 'Closed'
39
+ state = LocalizerTestModel.aasm.states.detect {|s| s == :closed}
40
+ expect(state.localized_name).to eq('Closed')
41
+ expect(state.human_name).to eq('Closed')
38
42
  end
39
43
  end
40
44
 
@@ -52,23 +56,23 @@ describe AASM::Localizer, "new style" do
52
56
  let (:foo_opened) { LocalizerTestModel.new }
53
57
  let (:foo_closed) { LocalizerTestModel.new.tap { |x| x.aasm_state = :closed } }
54
58
 
55
- context 'aasm_human_state' do
59
+ context 'aasm.human_state' do
56
60
  it 'should return translated state value' do
57
- foo_opened.aasm_human_state.should == "It's open now!"
61
+ expect(foo_opened.aasm.human_state).to eq("It's open now!")
58
62
  end
59
63
 
60
64
  it 'should return humanized value if not localized' do
61
- foo_closed.aasm_human_state.should == "Closed"
65
+ expect(foo_closed.aasm.human_state).to eq("Closed")
62
66
  end
63
67
  end
64
68
 
65
69
  context 'aasm_human_event_name' do
66
70
  it 'should return translated event name' do
67
- LocalizerTestModel.aasm_human_event_name(:close).should == "Let's close it!"
71
+ expect(LocalizerTestModel.aasm_human_event_name(:close)).to eq("Let's close it!")
68
72
  end
69
73
 
70
74
  it 'should return humanized event name' do
71
- LocalizerTestModel.aasm_human_event_name(:open).should == "Open"
75
+ expect(LocalizerTestModel.aasm_human_event_name(:open)).to eq("Open")
72
76
  end
73
77
  end
74
78
  end
@@ -87,23 +91,23 @@ describe AASM::Localizer, "deprecated style" do
87
91
  let (:foo_opened) { LocalizerTestModel.new }
88
92
  let (:foo_closed) { LocalizerTestModel.new.tap { |x| x.aasm_state = :closed } }
89
93
 
90
- context 'aasm_human_state' do
94
+ context 'aasm.human_state' do
91
95
  it 'should return translated state value' do
92
- foo_opened.aasm_human_state.should == "It's open now!"
96
+ expect(foo_opened.aasm.human_state).to eq("It's open now!")
93
97
  end
94
98
 
95
99
  it 'should return humanized value if not localized' do
96
- foo_closed.aasm_human_state.should == "Closed"
100
+ expect(foo_closed.aasm.human_state).to eq("Closed")
97
101
  end
98
102
  end
99
103
 
100
104
  context 'aasm_human_event_name' do
101
105
  it 'should return translated event name' do
102
- LocalizerTestModel.aasm_human_event_name(:close).should == "Let's close it!"
106
+ expect(LocalizerTestModel.aasm_human_event_name(:close)).to eq("Let's close it!")
103
107
  end
104
108
 
105
109
  it 'should return humanized event name' do
106
- LocalizerTestModel.aasm_human_event_name(:open).should == "Open"
110
+ expect(LocalizerTestModel.aasm_human_event_name(:open)).to eq("Open")
107
111
  end
108
112
  end
109
113
  end
@@ -2,8 +2,8 @@
2
2
 
3
3
  # describe "state machines" do
4
4
 
5
- # def number_of_objects(clazz)
6
- # ObjectSpace.each_object(clazz) {}
5
+ # def number_of_objects(klass)
6
+ # ObjectSpace.each_object(klass) {}
7
7
  # end
8
8
 
9
9
  # def machines
@@ -5,8 +5,8 @@ describe "the new dsl" do
5
5
  let(:process) {ProcessWithNewDsl.new}
6
6
 
7
7
  it 'should not conflict with other event or state methods' do
8
- lambda {ProcessWithNewDsl.state}.should raise_error(RuntimeError, "wrong state method")
9
- lambda {ProcessWithNewDsl.event}.should raise_error(RuntimeError, "wrong event method")
8
+ expect {ProcessWithNewDsl.state}.to raise_error(RuntimeError, "wrong state method")
9
+ expect {ProcessWithNewDsl.event}.to raise_error(RuntimeError, "wrong event method")
10
10
  end
11
11
 
12
12
  end