simple_state_machine 0.5.2 → 0.6.1
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.
- checksums.yaml +7 -0
- data/.github/workflows/build.yml +46 -0
- data/.gitignore +3 -0
- data/.travis.yml +17 -0
- data/Changelog.rdoc +16 -0
- data/Gemfile +7 -0
- data/README.rdoc +154 -99
- data/examples/conversation.rb +5 -5
- data/examples/lamp.rb +5 -5
- data/examples/relationship.rb +8 -8
- data/examples/traffic_light.rb +3 -3
- data/examples/user.rb +8 -4
- data/gemfiles/Gemfile.activerecord-5.2.x +9 -0
- data/gemfiles/Gemfile.activerecord-6.0.x +9 -0
- data/gemfiles/Gemfile.activerecord-6.1.x +8 -0
- data/gemfiles/Gemfile.activerecord-main.x +9 -0
- data/gemfiles/Gemfile.basic +6 -0
- data/lib/simple_state_machine/.DS_Store +0 -0
- data/lib/simple_state_machine/active_record.rb +2 -64
- data/lib/simple_state_machine/decorator/active_record.rb +68 -0
- data/lib/simple_state_machine/decorator/default.rb +91 -0
- data/lib/simple_state_machine/railtie.rb +1 -1
- data/lib/simple_state_machine/simple_state_machine.rb +8 -251
- data/lib/simple_state_machine/state_machine.rb +88 -0
- data/lib/simple_state_machine/state_machine_definition.rb +72 -0
- data/lib/simple_state_machine/tools/graphviz.rb +21 -0
- data/lib/simple_state_machine/tools/inspector.rb +44 -0
- data/lib/simple_state_machine/transition.rb +40 -0
- data/lib/simple_state_machine/version.rb +1 -1
- data/lib/simple_state_machine.rb +13 -3
- data/lib/tasks/graphviz.rake +31 -0
- data/simple_state_machine.gemspec +14 -24
- data/spec/.DS_Store +0 -0
- data/spec/active_record_spec.rb +216 -179
- data/spec/{decorator_spec.rb → decorator/default_spec.rb} +32 -32
- data/spec/examples_spec.rb +17 -17
- data/spec/mountable_spec.rb +26 -14
- data/spec/simple_state_machine_spec.rb +128 -92
- data/spec/spec_helper.rb +18 -5
- data/spec/state_machine_definition_spec.rb +48 -34
- data/spec/state_machine_spec.rb +36 -2
- data/spec/tools/graphviz_spec.rb +30 -0
- data/spec/tools/inspector_spec.rb +70 -0
- metadata +54 -128
- data/autotest/discover.rb +0 -1
- data/lib/tasks/graphiz.rake +0 -13
- data/rails/graphiz.rake +0 -16
| @@ -1,6 +1,6 @@ | |
| 1 | 
            -
            require  | 
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 2 |  | 
| 3 | 
            -
            describe SimpleStateMachine::Decorator do
         | 
| 3 | 
            +
            describe SimpleStateMachine::Decorator::Default do
         | 
| 4 4 |  | 
| 5 5 | 
             
              context "given a class" do
         | 
| 6 6 | 
             
                before do
         | 
| @@ -10,7 +10,7 @@ describe SimpleStateMachine::Decorator do | |
| 10 10 | 
             
                      @state_machine_definition ||= SimpleStateMachine::StateMachineDefinition.new
         | 
| 11 11 | 
             
                    end
         | 
| 12 12 | 
             
                  end
         | 
| 13 | 
            -
                  decorator =  | 
| 13 | 
            +
                  decorator = described_class.new klass
         | 
| 14 14 | 
             
                  decorator.decorate SimpleStateMachine::Transition.new(:event, :state1, :state2)
         | 
| 15 15 | 
             
                  @instance = klass.new
         | 
| 16 16 | 
             
                  @instance.state = 'state1'
         | 
| @@ -18,26 +18,26 @@ describe SimpleStateMachine::Decorator do | |
| 18 18 |  | 
| 19 19 | 
             
                describe "#initialize" do
         | 
| 20 20 | 
             
                  it "defines a state_machine method" do
         | 
| 21 | 
            -
                    @instance.state_machine. | 
| 21 | 
            +
                    expect(@instance.state_machine).to be_an(SimpleStateMachine::StateMachine)
         | 
| 22 22 | 
             
                  end
         | 
| 23 23 |  | 
| 24 24 | 
             
                  it "defines a state getter method" do
         | 
| 25 | 
            -
                    @instance. | 
| 25 | 
            +
                    expect(@instance).to respond_to(:state)
         | 
| 26 26 | 
             
                  end
         | 
| 27 27 |  | 
| 28 28 | 
             
                  it "defines a state setter method" do
         | 
| 29 | 
            -
                    @instance. | 
| 29 | 
            +
                    expect(@instance).to respond_to(:state=)
         | 
| 30 30 | 
             
                  end
         | 
| 31 31 | 
             
                end
         | 
| 32 32 |  | 
| 33 33 | 
             
                describe "#decorate" do
         | 
| 34 34 | 
             
                  it "defines state_helper_methods for both states" do
         | 
| 35 | 
            -
                    @instance.state1 | 
| 36 | 
            -
                    @instance.state2 | 
| 35 | 
            +
                    expect(@instance.state1?).to  eq(true)
         | 
| 36 | 
            +
                    expect(@instance.state2?).to  eq(false)
         | 
| 37 37 | 
             
                  end
         | 
| 38 | 
            -
             | 
| 38 | 
            +
             | 
| 39 39 | 
             
                  it "defines an event method" do
         | 
| 40 | 
            -
                    @instance. | 
| 40 | 
            +
                    expect(@instance).to respond_to(:event)
         | 
| 41 41 | 
             
                  end
         | 
| 42 42 | 
             
                end
         | 
| 43 43 | 
             
              end
         | 
| @@ -55,7 +55,7 @@ describe SimpleStateMachine::Decorator do | |
| 55 55 | 
             
                    def event()   "predefined method" end
         | 
| 56 56 | 
             
                  end
         | 
| 57 57 | 
             
                  transition =  SimpleStateMachine::Transition.new(:event, :state1, :state2)
         | 
| 58 | 
            -
                  decorator =  | 
| 58 | 
            +
                  decorator = described_class.new klass
         | 
| 59 59 | 
             
                  decorator.decorate transition
         | 
| 60 60 | 
             
                  klass.state_machine_definition.transitions << transition
         | 
| 61 61 | 
             
                  @instance = klass.new
         | 
| @@ -64,30 +64,30 @@ describe SimpleStateMachine::Decorator do | |
| 64 64 |  | 
| 65 65 | 
             
                describe "#initialize" do
         | 
| 66 66 | 
             
                  it "defines a state_machine method" do
         | 
| 67 | 
            -
                    @instance.state_machine. | 
| 67 | 
            +
                    expect(@instance.state_machine).to be_an(SimpleStateMachine::StateMachine)
         | 
| 68 68 | 
             
                  end
         | 
| 69 69 |  | 
| 70 70 | 
             
                  it "defines a state getter method" do
         | 
| 71 | 
            -
                    @instance. | 
| 71 | 
            +
                    expect(@instance).to respond_to(:state)
         | 
| 72 72 | 
             
                  end
         | 
| 73 73 |  | 
| 74 74 | 
             
                  it "defines a state setter method" do
         | 
| 75 | 
            -
                    @instance. | 
| 75 | 
            +
                    expect(@instance).to respond_to(:state=)
         | 
| 76 76 | 
             
                  end
         | 
| 77 77 | 
             
                end
         | 
| 78 78 |  | 
| 79 79 | 
             
                describe "#decorate" do
         | 
| 80 80 | 
             
                  it "does not overwrite predefined state_helper_methods" do
         | 
| 81 | 
            -
                    @instance.state1 | 
| 82 | 
            -
                    @instance.state2 | 
| 81 | 
            +
                    expect(@instance.state1?).to  eq("state1")
         | 
| 82 | 
            +
                    expect(@instance.state2?).to  eq("state2")
         | 
| 83 83 | 
             
                  end
         | 
| 84 84 |  | 
| 85 85 | 
             
                  it "does not overwrite predefined event method" do
         | 
| 86 | 
            -
                    @instance.event. | 
| 86 | 
            +
                    expect(@instance.event).to eq("predefined method")
         | 
| 87 87 | 
             
                  end
         | 
| 88 88 | 
             
                end
         | 
| 89 89 | 
             
              end
         | 
| 90 | 
            -
             | 
| 90 | 
            +
             | 
| 91 91 | 
             
              context "given a class with predefined protected methods" do
         | 
| 92 92 | 
             
                before do
         | 
| 93 93 | 
             
                  klass = Class.new do
         | 
| @@ -102,7 +102,7 @@ describe SimpleStateMachine::Decorator do | |
| 102 102 | 
             
                    def event()   "predefined method" end
         | 
| 103 103 | 
             
                  end
         | 
| 104 104 | 
             
                  transition =  SimpleStateMachine::Transition.new(:event, :state1, :state2)
         | 
| 105 | 
            -
                  decorator =  | 
| 105 | 
            +
                  decorator = described_class.new klass
         | 
| 106 106 | 
             
                  decorator.decorate transition
         | 
| 107 107 | 
             
                  klass.state_machine_definition.transitions << transition
         | 
| 108 108 | 
             
                  @instance = klass.new
         | 
| @@ -111,22 +111,22 @@ describe SimpleStateMachine::Decorator do | |
| 111 111 |  | 
| 112 112 | 
             
                describe "#initialize" do
         | 
| 113 113 | 
             
                  it "defines a state_machine method" do
         | 
| 114 | 
            -
                    @instance.state_machine. | 
| 114 | 
            +
                    expect(@instance.state_machine).to be_an(SimpleStateMachine::StateMachine)
         | 
| 115 115 | 
             
                  end
         | 
| 116 116 |  | 
| 117 117 | 
             
                  it "defines a state getter method" do
         | 
| 118 | 
            -
                    @instance. | 
| 118 | 
            +
                    expect(@instance).to respond_to(:state)
         | 
| 119 119 | 
             
                  end
         | 
| 120 120 |  | 
| 121 121 | 
             
                  it "defines a state setter method" do
         | 
| 122 | 
            -
                    @instance. | 
| 122 | 
            +
                    expect(@instance).to respond_to(:state=)
         | 
| 123 123 | 
             
                  end
         | 
| 124 124 | 
             
                end
         | 
| 125 125 |  | 
| 126 126 | 
             
                describe "#decorate" do
         | 
| 127 127 | 
             
                  it "does not overwrite predefined protected state_helper_methods" do
         | 
| 128 | 
            -
                    @instance.send(:state1?). | 
| 129 | 
            -
                    @instance.send(:state2?). | 
| 128 | 
            +
                    expect(@instance.send(:state1?)).to  eq("state1")
         | 
| 129 | 
            +
                    expect(@instance.send(:state2?)).to  eq("state2")
         | 
| 130 130 | 
             
                  end
         | 
| 131 131 |  | 
| 132 132 | 
             
                  it "keeps predefined protected state_helper_methods protected" do
         | 
| @@ -135,7 +135,7 @@ describe SimpleStateMachine::Decorator do | |
| 135 135 | 
             
                  end
         | 
| 136 136 |  | 
| 137 137 | 
             
                  it "does not overwrite predefined protected event method" do
         | 
| 138 | 
            -
                    @instance.event. | 
| 138 | 
            +
                    expect(@instance.event).to eq("predefined method")
         | 
| 139 139 | 
             
                  end
         | 
| 140 140 | 
             
                end
         | 
| 141 141 | 
             
              end
         | 
| @@ -154,7 +154,7 @@ describe SimpleStateMachine::Decorator do | |
| 154 154 | 
             
                    def event()   "predefined method" end
         | 
| 155 155 | 
             
                  end
         | 
| 156 156 | 
             
                  transition =  SimpleStateMachine::Transition.new(:event, :state1, :state2)
         | 
| 157 | 
            -
                  decorator =  | 
| 157 | 
            +
                  decorator = described_class.new klass
         | 
| 158 158 | 
             
                  decorator.decorate transition
         | 
| 159 159 | 
             
                  klass.state_machine_definition.transitions << transition
         | 
| 160 160 | 
             
                  @instance = klass.new
         | 
| @@ -163,22 +163,22 @@ describe SimpleStateMachine::Decorator do | |
| 163 163 |  | 
| 164 164 | 
             
                describe "#initialize" do
         | 
| 165 165 | 
             
                  it "defines a state_machine method" do
         | 
| 166 | 
            -
                    @instance.state_machine. | 
| 166 | 
            +
                    expect(@instance.state_machine).to be_an(SimpleStateMachine::StateMachine)
         | 
| 167 167 | 
             
                  end
         | 
| 168 168 |  | 
| 169 169 | 
             
                  it "defines a state getter method" do
         | 
| 170 | 
            -
                    @instance. | 
| 170 | 
            +
                    expect(@instance).to respond_to(:state)
         | 
| 171 171 | 
             
                  end
         | 
| 172 172 |  | 
| 173 173 | 
             
                  it "defines a state setter method" do
         | 
| 174 | 
            -
                    @instance. | 
| 174 | 
            +
                    expect(@instance).to respond_to(:state=)
         | 
| 175 175 | 
             
                  end
         | 
| 176 176 | 
             
                end
         | 
| 177 177 |  | 
| 178 178 | 
             
                describe "#decorate" do
         | 
| 179 179 | 
             
                  it "does not overwrite predefined private state_helper_methods" do
         | 
| 180 | 
            -
                    @instance.send(:state1?). | 
| 181 | 
            -
                    @instance.send(:state2?). | 
| 180 | 
            +
                    expect(@instance.send(:state1?)).to  eq("state1")
         | 
| 181 | 
            +
                    expect(@instance.send(:state2?)).to  eq("state2")
         | 
| 182 182 | 
             
                  end
         | 
| 183 183 |  | 
| 184 184 | 
             
                  it "keeps predefined private state_helper_methods private" do
         | 
| @@ -187,7 +187,7 @@ describe SimpleStateMachine::Decorator do | |
| 187 187 | 
             
                  end
         | 
| 188 188 |  | 
| 189 189 | 
             
                  it "does not overwrite predefined protected event method" do
         | 
| 190 | 
            -
                    @instance.event. | 
| 190 | 
            +
                    expect(@instance.event).to eq("predefined method")
         | 
| 191 191 | 
             
                  end
         | 
| 192 192 | 
             
                end
         | 
| 193 193 | 
             
              end
         | 
    
        data/spec/examples_spec.rb
    CHANGED
    
    | @@ -1,57 +1,57 @@ | |
| 1 | 
            -
            require  | 
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 2 |  | 
| 3 3 | 
             
            describe "Examples" do
         | 
| 4 4 | 
             
              describe "TrafficLight" do
         | 
| 5 5 | 
             
                it "changes to the next state" do
         | 
| 6 6 | 
             
                  tl = TrafficLight.new
         | 
| 7 | 
            -
                  tl. | 
| 7 | 
            +
                  expect(tl).to be_green
         | 
| 8 8 | 
             
                  tl.change_state
         | 
| 9 | 
            -
                  tl. | 
| 9 | 
            +
                  expect(tl).to be_orange
         | 
| 10 10 | 
             
                  tl.change_state
         | 
| 11 | 
            -
                  tl. | 
| 11 | 
            +
                  expect(tl).to be_red
         | 
| 12 12 | 
             
                  tl.change_state
         | 
| 13 | 
            -
                  tl. | 
| 13 | 
            +
                  expect(tl).to be_green
         | 
| 14 14 | 
             
                end
         | 
| 15 15 | 
             
              end
         | 
| 16 | 
            -
             | 
| 16 | 
            +
             | 
| 17 17 | 
             
              describe "Lamp" do
         | 
| 18 18 | 
             
                it "changes between :on and :off" do
         | 
| 19 19 | 
             
                  lamp = Lamp.new
         | 
| 20 | 
            -
                  lamp. | 
| 20 | 
            +
                  expect(lamp).to be_off
         | 
| 21 21 | 
             
                  lamp.push_button1
         | 
| 22 | 
            -
                  lamp. | 
| 22 | 
            +
                  expect(lamp).to be_on
         | 
| 23 23 | 
             
                  lamp.push_button2
         | 
| 24 | 
            -
                  lamp. | 
| 24 | 
            +
                  expect(lamp).to be_off
         | 
| 25 25 | 
             
                  lamp.push_button2
         | 
| 26 | 
            -
                  lamp. | 
| 26 | 
            +
                  expect(lamp).to be_on
         | 
| 27 27 | 
             
                  lamp.push_button1
         | 
| 28 | 
            -
                  lamp. | 
| 28 | 
            +
                  expect(lamp).to be_off
         | 
| 29 29 | 
             
                end
         | 
| 30 30 | 
             
              end
         | 
| 31 | 
            -
             | 
| 31 | 
            +
             | 
| 32 32 | 
             
              describe "Conversation" do
         | 
| 33 33 | 
             
                it "is :unread by default" do
         | 
| 34 34 | 
             
                  conversation = Conversation.new
         | 
| 35 | 
            -
                  conversation. | 
| 35 | 
            +
                  expect(conversation).to be_unread
         | 
| 36 36 | 
             
                end
         | 
| 37 | 
            -
             | 
| 37 | 
            +
             | 
| 38 38 | 
             
                it "changes to read on view" do
         | 
| 39 39 | 
             
                  conversation = Conversation.new
         | 
| 40 40 | 
             
                  conversation.view
         | 
| 41 | 
            -
                  conversation. | 
| 41 | 
            +
                  expect(conversation).to be_read
         | 
| 42 42 | 
             
                end
         | 
| 43 43 |  | 
| 44 44 | 
             
                it "changes to closed on close" do
         | 
| 45 45 | 
             
                  conversation = Conversation.new
         | 
| 46 46 | 
             
                  conversation.close
         | 
| 47 | 
            -
                  conversation. | 
| 47 | 
            +
                  expect(conversation).to be_closed
         | 
| 48 48 | 
             
                end
         | 
| 49 49 |  | 
| 50 50 | 
             
                it "changes to closed on close if :read" do
         | 
| 51 51 | 
             
                  conversation = Conversation.new
         | 
| 52 52 | 
             
                  conversation.view
         | 
| 53 53 | 
             
                  conversation.close
         | 
| 54 | 
            -
                  conversation. | 
| 54 | 
            +
                  expect(conversation).to be_closed
         | 
| 55 55 | 
             
                end
         | 
| 56 56 |  | 
| 57 57 | 
             
              end
         | 
    
        data/spec/mountable_spec.rb
    CHANGED
    
    | @@ -1,24 +1,36 @@ | |
| 1 | 
            -
            require  | 
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 2 |  | 
| 3 | 
            -
            describe  | 
| 4 | 
            -
               | 
| 5 | 
            -
                 | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 8 | 
            -
             | 
| 9 | 
            -
                  end
         | 
| 3 | 
            +
            describe SimpleStateMachine::Mountable do
         | 
| 4 | 
            +
              class MountableExample < SimpleStateMachine::StateMachineDefinition
         | 
| 5 | 
            +
                event(:event, :state1 => :state2)
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                def decorator_class
         | 
| 8 | 
            +
                  SimpleStateMachine::Decorator::Default
         | 
| 10 9 | 
             
                end
         | 
| 11 | 
            -
             | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              let(:klass) do
         | 
| 13 | 
            +
                Class.new do
         | 
| 14 | 
            +
                  attr_accessor :event_called
         | 
| 12 15 | 
             
                  extend SimpleStateMachine::Mountable
         | 
| 13 | 
            -
                   | 
| 16 | 
            +
                  mount_state_machine MountableExample
         | 
| 17 | 
            +
                  def event_without_managed_state
         | 
| 18 | 
            +
                    @event_called = true
         | 
| 19 | 
            +
                  end
         | 
| 14 20 | 
             
                end
         | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
              subject do
         | 
| 23 | 
            +
                klass.new.tap{|i| i.state = 'state1' }
         | 
| 17 24 | 
             
              end
         | 
| 18 25 |  | 
| 19 26 | 
             
              it "has state_helper methods" do
         | 
| 20 | 
            -
                 | 
| 21 | 
            -
                 | 
| 27 | 
            +
                expect(subject).to be_state1
         | 
| 28 | 
            +
                expect(subject).not_to be_state2
         | 
| 22 29 | 
             
              end
         | 
| 23 30 |  | 
| 31 | 
            +
              it "calls existing methods" do
         | 
| 32 | 
            +
                subject.event
         | 
| 33 | 
            +
                expect(subject).to be_state2
         | 
| 34 | 
            +
                expect(subject.event_called).to eq(true)
         | 
| 35 | 
            +
              end
         | 
| 24 36 | 
             
            end
         | 
| @@ -1,126 +1,162 @@ | |
| 1 | 
            -
            require  | 
| 2 | 
            -
            require 'cgi'
         | 
| 1 | 
            +
            require 'spec_helper'
         | 
| 3 2 |  | 
| 4 3 | 
             
            describe SimpleStateMachine do
         | 
| 5 | 
            -
             | 
| 4 | 
            +
             | 
| 6 5 | 
             
              it "has an error that extends RuntimeError" do
         | 
| 7 | 
            -
                SimpleStateMachine::IllegalStateTransitionError.superclass. | 
| 6 | 
            +
                expect(SimpleStateMachine::IllegalStateTransitionError.superclass).to eq(RuntimeError)
         | 
| 7 | 
            +
              end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              let(:klass) do
         | 
| 10 | 
            +
                Class.new do
         | 
| 11 | 
            +
                  extend SimpleStateMachine
         | 
| 12 | 
            +
                  def initialize(state = 'state1')
         | 
| 13 | 
            +
                    @state = state
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
                end
         | 
| 8 16 | 
             
              end
         | 
| 9 17 |  | 
| 10 18 | 
             
              describe ".event" do
         | 
| 11 19 |  | 
| 12 | 
            -
                 | 
| 13 | 
            -
                   | 
| 14 | 
            -
                     | 
| 15 | 
            -
                     | 
| 16 | 
            -
                       | 
| 20 | 
            +
                it "returns what the decorated method returns" do
         | 
| 21 | 
            +
                  klass.instance_eval do
         | 
| 22 | 
            +
                    event :event1,  :state1 => :state2
         | 
| 23 | 
            +
                    define_method :event2 do
         | 
| 24 | 
            +
                      'event2'
         | 
| 17 25 | 
             
                    end
         | 
| 26 | 
            +
                    event :event2, :state2 => :state3
         | 
| 18 27 | 
             
                  end
         | 
| 28 | 
            +
                  subject = klass.new
         | 
| 29 | 
            +
                  expect(subject.event1).to eq(nil)
         | 
| 30 | 
            +
                  expect(subject.event2).to eq('event2')
         | 
| 19 31 | 
             
                end
         | 
| 20 32 |  | 
| 21 | 
            -
                it " | 
| 22 | 
            -
                  klass = Class.new(@klass)
         | 
| 33 | 
            +
                it "calls existing methods" do
         | 
| 23 34 | 
             
                  klass.instance_eval do
         | 
| 24 | 
            -
                     | 
| 35 | 
            +
                    attr_accessor :event_called
         | 
| 36 | 
            +
                    define_method :event do
         | 
| 37 | 
            +
                      @event_called = true
         | 
| 38 | 
            +
                    end
         | 
| 39 | 
            +
                    event :event, :state1 => :state2
         | 
| 25 40 | 
             
                  end
         | 
| 26 | 
            -
                   | 
| 27 | 
            -
                   | 
| 28 | 
            -
                   | 
| 29 | 
            -
                  example.should be_state2
         | 
| 30 | 
            -
                  example.event
         | 
| 31 | 
            -
                  example.should be_state3
         | 
| 41 | 
            +
                  subject = klass.new
         | 
| 42 | 
            +
                  subject.event
         | 
| 43 | 
            +
                  expect(subject.event_called).to eq(true)
         | 
| 32 44 | 
             
                end
         | 
| 33 45 |  | 
| 34 | 
            -
                 | 
| 35 | 
            -
                   | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 46 | 
            +
                context "given an event has multiple transitions" do
         | 
| 47 | 
            +
                  before do
         | 
| 48 | 
            +
                    klass.instance_eval do
         | 
| 49 | 
            +
                      event :event, :state1 => :state2, :state2 => :state3
         | 
| 50 | 
            +
                    end
         | 
| 38 51 | 
             
                  end
         | 
| 39 | 
            -
                  example = klass.new
         | 
| 40 | 
            -
                  example.event
         | 
| 41 | 
            -
                  example.should be_state3
         | 
| 42 | 
            -
                  example = klass.new 'state2'
         | 
| 43 | 
            -
                  example.should be_state2
         | 
| 44 | 
            -
                  example.event
         | 
| 45 | 
            -
                  example.should be_state3
         | 
| 46 | 
            -
                end
         | 
| 47 52 |  | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 50 | 
            -
             | 
| 51 | 
            -
                    event | 
| 52 | 
            -
                     | 
| 53 | 
            +
                  it "changes state for all transitions" do
         | 
| 54 | 
            +
                    subject = klass.new
         | 
| 55 | 
            +
                    expect(subject).to be_state1
         | 
| 56 | 
            +
                    subject.event
         | 
| 57 | 
            +
                    expect(subject).to be_state2
         | 
| 58 | 
            +
                    subject.event
         | 
| 59 | 
            +
                    expect(subject).to be_state3
         | 
| 53 60 | 
             
                  end
         | 
| 54 | 
            -
                  example = klass.new
         | 
| 55 | 
            -
                  example.event
         | 
| 56 | 
            -
                  example.should be_state3
         | 
| 57 | 
            -
                  example = klass.new 'state2'
         | 
| 58 | 
            -
                  example.should be_state2
         | 
| 59 | 
            -
                  example.event
         | 
| 60 | 
            -
                  example.should be_state3
         | 
| 61 61 | 
             
                end
         | 
| 62 62 |  | 
| 63 | 
            -
                 | 
| 64 | 
            -
                   | 
| 65 | 
            -
             | 
| 66 | 
            -
             | 
| 67 | 
            -
             | 
| 68 | 
            -
                   | 
| 69 | 
            -
             | 
| 70 | 
            -
                   | 
| 71 | 
            -
             | 
| 63 | 
            +
                context "given an event has multiple from states" do
         | 
| 64 | 
            +
                  before do
         | 
| 65 | 
            +
                    klass.instance_eval do
         | 
| 66 | 
            +
                      event :event, [:state1, :state2] => :state3
         | 
| 67 | 
            +
                    end
         | 
| 68 | 
            +
                  end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                  it "changes state for all from states" do
         | 
| 71 | 
            +
                    subject = klass.new
         | 
| 72 | 
            +
                    subject.event
         | 
| 73 | 
            +
                    expect(subject).to be_state3
         | 
| 74 | 
            +
                    subject = klass.new 'state2'
         | 
| 75 | 
            +
                    expect(subject).to be_state2
         | 
| 76 | 
            +
                    subject.event
         | 
| 77 | 
            +
                    expect(subject).to be_state3
         | 
| 78 | 
            +
                  end
         | 
| 72 79 | 
             
                end
         | 
| 73 80 |  | 
| 74 | 
            -
                 | 
| 75 | 
            -
                   | 
| 76 | 
            -
             | 
| 77 | 
            -
             | 
| 78 | 
            -
                       | 
| 81 | 
            +
                context "given an event has :all as from state" do
         | 
| 82 | 
            +
                  before do
         | 
| 83 | 
            +
                    klass.instance_eval do
         | 
| 84 | 
            +
                      event :other_event, :state1 => :state2
         | 
| 85 | 
            +
                      event :event, :all => :state3
         | 
| 79 86 | 
             
                    end
         | 
| 80 | 
            -
                    event :raise_error, :state1 => :state2, RuntimeError => :failed
         | 
| 81 87 | 
             
                  end
         | 
| 82 | 
            -
             | 
| 83 | 
            -
                   | 
| 84 | 
            -
             | 
| 85 | 
            -
             | 
| 88 | 
            +
             | 
| 89 | 
            +
                  it "changes state from all states" do
         | 
| 90 | 
            +
                    subject = klass.new
         | 
| 91 | 
            +
                    subject.event
         | 
| 92 | 
            +
                    expect(subject).to be_state3
         | 
| 93 | 
            +
                    subject = klass.new 'state2'
         | 
| 94 | 
            +
                    expect(subject).to be_state2
         | 
| 95 | 
            +
                    subject.event
         | 
| 96 | 
            +
                    expect(subject).to be_state3
         | 
| 97 | 
            +
                  end
         | 
| 86 98 | 
             
                end
         | 
| 87 | 
            -
             | 
| 88 | 
            -
                 | 
| 89 | 
            -
                   | 
| 90 | 
            -
             | 
| 91 | 
            -
             | 
| 92 | 
            -
                     | 
| 93 | 
            -
                  end | 
| 94 | 
            -
             | 
| 95 | 
            -
                   | 
| 99 | 
            +
             | 
| 100 | 
            +
                context "given state is a symbol instead of a string" do
         | 
| 101 | 
            +
                  before do
         | 
| 102 | 
            +
                    klass.instance_eval do
         | 
| 103 | 
            +
                      event :event, :state1 => :state2
         | 
| 104 | 
            +
                    end
         | 
| 105 | 
            +
                  end
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                  it "changes state" do
         | 
| 108 | 
            +
                    subject = klass.new :state1
         | 
| 109 | 
            +
                    expect(subject.state).to eq(:state1)
         | 
| 110 | 
            +
                    subject.send(:event)
         | 
| 111 | 
            +
                    expect(subject).to be_state2
         | 
| 112 | 
            +
                  end
         | 
| 96 113 | 
             
                end
         | 
| 97 114 |  | 
| 98 | 
            -
                 | 
| 99 | 
            -
                   | 
| 100 | 
            -
             | 
| 101 | 
            -
                     | 
| 102 | 
            -
             | 
| 103 | 
            -
             | 
| 115 | 
            +
                context "given an RuntimeError begin state" do
         | 
| 116 | 
            +
                  it "changes state to error_state when error can be caught" do
         | 
| 117 | 
            +
                    class_with_error = Class.new(klass)
         | 
| 118 | 
            +
                    class_with_error.instance_eval do
         | 
| 119 | 
            +
                      define_method :raise_error do
         | 
| 120 | 
            +
                        raise RuntimeError.new
         | 
| 121 | 
            +
                      end
         | 
| 122 | 
            +
                      event :raise_error, :state1 => :state2, RuntimeError => :failed
         | 
| 104 123 | 
             
                    end
         | 
| 105 | 
            -
                     | 
| 106 | 
            -
             | 
| 107 | 
            -
             | 
| 108 | 
            -
             | 
| 109 | 
            -
                   | 
| 124 | 
            +
                    subject = class_with_error.new
         | 
| 125 | 
            +
                    expect(subject).to be_state1
         | 
| 126 | 
            +
                    subject.raise_error
         | 
| 127 | 
            +
                    expect(subject).to be_failed
         | 
| 128 | 
            +
                  end
         | 
| 129 | 
            +
             | 
| 130 | 
            +
                  it "changes state to error_state when error superclass can be caught" do
         | 
| 131 | 
            +
                    error_subclass   = Class.new(RuntimeError)
         | 
| 132 | 
            +
                    class_with_error = Class.new(klass)
         | 
| 133 | 
            +
                    class_with_error.instance_eval do
         | 
| 134 | 
            +
                      define_method :raise_error do
         | 
| 135 | 
            +
                        raise error_subclass.new
         | 
| 136 | 
            +
                      end
         | 
| 137 | 
            +
                      event :raise_error, :state1 => :state2, RuntimeError => :failed
         | 
| 138 | 
            +
                    end
         | 
| 139 | 
            +
                    subject = class_with_error.new
         | 
| 140 | 
            +
                    expect(subject).to be_state1
         | 
| 141 | 
            +
                    subject.raise_error
         | 
| 142 | 
            +
                    expect(subject).to be_failed
         | 
| 143 | 
            +
                  end
         | 
| 110 144 | 
             
                end
         | 
| 111 145 |  | 
| 112 | 
            -
                 | 
| 113 | 
            -
                   | 
| 114 | 
            -
             | 
| 115 | 
            -
             | 
| 116 | 
            -
             | 
| 117 | 
            -
                      @event_called = true
         | 
| 146 | 
            +
                context "given an invalid state_transition is called" do
         | 
| 147 | 
            +
                  before do
         | 
| 148 | 
            +
                    klass.instance_eval do
         | 
| 149 | 
            +
                      event :event,  :state1 => :state2
         | 
| 150 | 
            +
                      event :event2, :state2 => :state3
         | 
| 118 151 | 
             
                    end
         | 
| 119 | 
            -
             | 
| 120 | 
            -
             | 
| 121 | 
            -
                   | 
| 122 | 
            -
             | 
| 123 | 
            -
             | 
| 152 | 
            +
                  end
         | 
| 153 | 
            +
             | 
| 154 | 
            +
                  it "raises an IllegalStateTransitionError" do
         | 
| 155 | 
            +
                    subject = klass.new
         | 
| 156 | 
            +
                    expect { subject.event2 }.to raise_error(
         | 
| 157 | 
            +
                        SimpleStateMachine::IllegalStateTransitionError,
         | 
| 158 | 
            +
                        "You cannot 'event2' when state is 'state1'")
         | 
| 159 | 
            +
                  end
         | 
| 124 160 | 
             
                end
         | 
| 125 161 |  | 
| 126 162 | 
             
              end
         | 
    
        data/spec/spec_helper.rb
    CHANGED
    
    | @@ -1,7 +1,20 @@ | |
| 1 | 
            -
             | 
| 2 | 
            -
             | 
| 1 | 
            +
            require "rubygems"
         | 
| 2 | 
            +
            require "bundler"
         | 
| 3 | 
            +
            Bundler.require :test
         | 
| 4 | 
            +
            begin
         | 
| 5 | 
            +
              require 'active_record'
         | 
| 6 | 
            +
            rescue LoadError
         | 
| 7 | 
            +
              puts "Skipping ActiveRecord specs"
         | 
| 8 | 
            +
            end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            ROOT = Pathname(File.expand_path(File.join(File.dirname(__FILE__), '..')))
         | 
| 11 | 
            +
            $LOAD_PATH << File.join(ROOT, 'lib')
         | 
| 12 | 
            +
            $LOAD_PATH << File.join(ROOT, 'spec')
         | 
| 13 | 
            +
            $LOAD_PATH << File.join(ROOT, 'examples')
         | 
| 14 | 
            +
             | 
| 3 15 | 
             
            require 'simple_state_machine'
         | 
| 4 | 
            -
            require 'examples | 
| 5 | 
            -
            require 'examples | 
| 6 | 
            -
            require 'examples | 
| 16 | 
            +
            require File.join(ROOT, 'examples', 'conversation.rb')
         | 
| 17 | 
            +
            require File.join(ROOT, 'examples', 'lamp.rb')
         | 
| 18 | 
            +
            require File.join(ROOT, 'examples', 'traffic_light.rb')
         | 
| 19 | 
            +
            require File.join(ROOT, 'examples', 'user.rb') if defined? ActiveRecord
         | 
| 7 20 |  |