finite 0.0.1 → 1.0.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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +6 -0
- data/README.md +88 -3
- data/Rakefile +5 -0
- data/finite.gemspec +3 -0
- data/lib/finite/class_methods.rb +13 -0
- data/lib/finite/event.rb +64 -1
- data/lib/finite/finite.rb +37 -0
- data/lib/finite/machine.rb +118 -2
- data/lib/finite/state.rb +36 -3
- data/lib/finite/transition.rb +20 -1
- data/lib/finite/version.rb +2 -1
- data/lib/finite.rb +17 -3
- data/spec/elevator_spec.rb +59 -0
- data/spec/event_spec.rb +64 -0
- data/spec/machine_spec.rb +67 -0
- data/spec/models/elevator.rb +94 -0
- data/spec/spec_helper.rb +20 -0
- data/spec/state_spec.rb +36 -0
- data/spec/transition_spec.rb +20 -0
- metadata +63 -3
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: efb775ca43d0ce5dddd4215fde0c54b5f764e097
         | 
| 4 | 
            +
              data.tar.gz: f617e7113c8f30f590c353dfa664776e74cb6c32
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 7e6a27d3620e1ed8a3d80099d9ff9ae7ac693ac04a81ba570b6048565e9cc6d94cd4a7ff69e5944489d652aec55ace9cabc9b688ae60d64e6c6d37762352f3e0
         | 
| 7 | 
            +
              data.tar.gz: ad0e60854b2334e045f78c35e0649e610e56abb9253ed0f22c6260972a8b469206e385052a1748dccc23ef84d7602bee120b44aafd2488aa6ab61f0583197d80
         | 
    
        data/.gitignore
    CHANGED
    
    
    
        data/.travis.yml
    ADDED
    
    
    
        data/README.md
    CHANGED
    
    | @@ -1,4 +1,5 @@ | |
| 1 | 
            -
            # Finite  | 
| 1 | 
            +
            # Finite [](https://travis-ci.org/kristenmills/finite)
         | 
| 2 | 
            +
             | 
| 2 3 |  | 
| 3 4 | 
             
            A simple state machine implementation for ruby
         | 
| 4 5 |  | 
| @@ -17,8 +18,92 @@ Or install it yourself as: | |
| 17 18 | 
             
                $ gem install finite
         | 
| 18 19 |  | 
| 19 20 | 
             
            ## Usage
         | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 21 | 
            +
            ```ruby
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            class Elevator
         | 
| 24 | 
            +
                include Finite
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                finite initial: :idle do
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                    before do
         | 
| 29 | 
            +
                        "This is called before every state but has no purpose other than to show it's existence in this example."
         | 
| 30 | 
            +
                    end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                    before :doors_closing do
         | 
| 33 | 
            +
                        puts 'Doors Closing!'
         | 
| 34 | 
            +
                    end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                    before :doors_opening do
         | 
| 37 | 
            +
                        puts 'Doors Opening!'
         | 
| 38 | 
            +
                    end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                    event :prepare do
         | 
| 41 | 
            +
                        go from: :idle, to: :doors_closing
         | 
| 42 | 
            +
                    end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                    event :go_up do
         | 
| 45 | 
            +
                        go from: :doors_closing, to: :elevator_going_up
         | 
| 46 | 
            +
                        after do
         | 
| 47 | 
            +
                            puts 'Going Up!'
         | 
| 48 | 
            +
                        end
         | 
| 49 | 
            +
                    end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                    event :go_down do
         | 
| 52 | 
            +
                        go from: :doors_closing, to: :elevator_going_down
         | 
| 53 | 
            +
                        after do
         | 
| 54 | 
            +
                            puts 'Going Down!'
         | 
| 55 | 
            +
                        end
         | 
| 56 | 
            +
                    end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                    event :start do
         | 
| 59 | 
            +
                        go from: [:elevator_going_up, :elevator_going_down], to: :moving
         | 
| 60 | 
            +
                    end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                    event :approach do
         | 
| 63 | 
            +
                        go from: :moving, to: :stopping
         | 
| 64 | 
            +
                    end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                    event :stop do
         | 
| 67 | 
            +
                        go from: :stopping, to: :doors_opening
         | 
| 68 | 
            +
                        before do
         | 
| 69 | 
            +
                            announce_floor
         | 
| 70 | 
            +
                        end
         | 
| 71 | 
            +
                    end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                    event :open_doors do
         | 
| 74 | 
            +
                        go from: :doors_opening, to: :at_floor
         | 
| 75 | 
            +
                    end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                    event :finish do
         | 
| 78 | 
            +
                        go from: :at_floor, to: :checking_next_dest
         | 
| 79 | 
            +
                    end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                    event :make_request do
         | 
| 82 | 
            +
                        go from: :checking_next_dest, to: :doors_closing
         | 
| 83 | 
            +
                    end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                    event :make_no_request do
         | 
| 86 | 
            +
                        go from: :checking_next_dest, to: :idle
         | 
| 87 | 
            +
                    end
         | 
| 88 | 
            +
                end
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                def announce_floor
         | 
| 91 | 
            +
                    puts "Arriving on floor #{rand(10)}"
         | 
| 92 | 
            +
                end
         | 
| 93 | 
            +
            end
         | 
| 94 | 
            +
            ```
         | 
| 95 | 
            +
             | 
| 96 | 
            +
            ```ruby
         | 
| 97 | 
            +
            elevator = Elevator.new
         | 
| 98 | 
            +
            elevator.current_state          # => :idle
         | 
| 99 | 
            +
            elevator.can_prepare?           # => true
         | 
| 100 | 
            +
            elevator.can_open_doors?        # => false
         | 
| 101 | 
            +
            elevator.open_doors             # => RuntimeError 'Invalid Transition'
         | 
| 102 | 
            +
            elevator.idle?                  # => true
         | 
| 103 | 
            +
            elevator.prepare                # => 'Doors Closing!'
         | 
| 104 | 
            +
            elevator.current_state          # => :doors_closing
         | 
| 105 | 
            +
            elevator.possible_events        # => [:go_up, :go_down]
         | 
| 106 | 
            +
            ```
         | 
| 22 107 |  | 
| 23 108 | 
             
            ## Contributing
         | 
| 24 109 |  | 
    
        data/Rakefile
    CHANGED
    
    
    
        data/finite.gemspec
    CHANGED
    
    | @@ -20,4 +20,7 @@ Gem::Specification.new do |spec| | |
| 20 20 |  | 
| 21 21 | 
             
              spec.add_development_dependency "bundler", "~> 1.3"
         | 
| 22 22 | 
             
              spec.add_development_dependency "rake"
         | 
| 23 | 
            +
              spec.add_development_dependency "simplecov"
         | 
| 24 | 
            +
              spec.add_development_dependency "rspec"
         | 
| 25 | 
            +
              spec.add_development_dependency "yard"
         | 
| 23 26 | 
             
            end
         | 
| @@ -0,0 +1,13 @@ | |
| 1 | 
            +
            module Finite
         | 
| 2 | 
            +
              # The class methods for any class that include the finite base
         | 
| 3 | 
            +
              module ClassMethods
         | 
| 4 | 
            +
                # The finite method for the dsl
         | 
| 5 | 
            +
                #
         | 
| 6 | 
            +
                # @param opts [Hash] any options including initial state
         | 
| 7 | 
            +
                # @param block [Block] the block of code that creates the state machine
         | 
| 8 | 
            +
                def finite(opts, &block)
         | 
| 9 | 
            +
                  StateMachine.machines ||= Hash.new
         | 
| 10 | 
            +
                  StateMachine.machines[self] = StateMachine.new(opts[:initial], self, &block)
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
            end
         | 
    
        data/lib/finite/event.rb
    CHANGED
    
    | @@ -1,5 +1,68 @@ | |
| 1 1 | 
             
            module Finite
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              # The event class. Represents an event in the state machine
         | 
| 2 4 | 
             
              class Event
         | 
| 3 | 
            -
             | 
| 5 | 
            +
             | 
| 6 | 
            +
                attr_reader :name, :transitions, :callbacks
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                # Create an event object
         | 
| 9 | 
            +
                #
         | 
| 10 | 
            +
                # @param name [Symbol] the name of the event
         | 
| 11 | 
            +
                # @param block [Block] the block of code in the event
         | 
| 12 | 
            +
                def initialize(name, &block)
         | 
| 13 | 
            +
                  @name = name
         | 
| 14 | 
            +
                  @transitions = Hash.new
         | 
| 15 | 
            +
                  @callbacks = {before: Array.new, after: Array.new}
         | 
| 16 | 
            +
                  instance_eval &block
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                # Are two events equal
         | 
| 20 | 
            +
                #
         | 
| 21 | 
            +
                # @param event [Object] the object you are comparing it to
         | 
| 22 | 
            +
                # @return true if they are equal false if not
         | 
| 23 | 
            +
                def ==(event)
         | 
| 24 | 
            +
                  if event.is_a? Event
         | 
| 25 | 
            +
                    @name == event.name
         | 
| 26 | 
            +
                  elsif event.is_a? Symbol
         | 
| 27 | 
            +
                    @name == event
         | 
| 28 | 
            +
                  else
         | 
| 29 | 
            +
                    false
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                # overrriden for puts and print
         | 
| 34 | 
            +
                def to_s
         | 
| 35 | 
            +
                  @name.to_s
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                # Overridden for p
         | 
| 39 | 
            +
                def inspect
         | 
| 40 | 
            +
                  @name
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                private
         | 
| 44 | 
            +
                # The transition method for the dsl
         | 
| 45 | 
            +
                #
         | 
| 46 | 
            +
                # @param opts [Hash] the options for a transition
         | 
| 47 | 
            +
                def go(opts)
         | 
| 48 | 
            +
                  options = []
         | 
| 49 | 
            +
                  if opts[:from].is_a? Array
         | 
| 50 | 
            +
                    opts[:from].each do |from|
         | 
| 51 | 
            +
                      options << {from: from, to: opts[:to]}
         | 
| 52 | 
            +
                    end
         | 
| 53 | 
            +
                  else
         | 
| 54 | 
            +
                    options << opts
         | 
| 55 | 
            +
                  end
         | 
| 56 | 
            +
                  options.each do |opt|
         | 
| 57 | 
            +
                    @transitions[opt[:from]] = Transition.new(opt)
         | 
| 58 | 
            +
                  end
         | 
| 59 | 
            +
                end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                # Create the callback methods
         | 
| 62 | 
            +
                [:after, :before].each do |callback|
         | 
| 63 | 
            +
                  define_method callback do |*args, &block|
         | 
| 64 | 
            +
                    @callbacks[callback] << block
         | 
| 65 | 
            +
                  end
         | 
| 66 | 
            +
                end
         | 
| 4 67 | 
             
              end
         | 
| 5 68 | 
             
            end
         | 
| @@ -0,0 +1,37 @@ | |
| 1 | 
            +
            module Finite
         | 
| 2 | 
            +
              # Get's the current state
         | 
| 3 | 
            +
              # @return the current state for an object
         | 
| 4 | 
            +
              def current_state
         | 
| 5 | 
            +
                machine = StateMachine.machines[self.class]
         | 
| 6 | 
            +
                @current_state or machine.states[machine.initial]
         | 
| 7 | 
            +
              end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              # Get's (and sets) the array of states
         | 
| 10 | 
            +
              # @return the array of states
         | 
| 11 | 
            +
              def states
         | 
| 12 | 
            +
                @states ||= StateMachine.machines[self.class].states
         | 
| 13 | 
            +
                @states
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              # Get's (and sets) the array of events
         | 
| 17 | 
            +
              # @return the array of events
         | 
| 18 | 
            +
              def events
         | 
| 19 | 
            +
                @events ||= StateMachine.machines[self.class].events
         | 
| 20 | 
            +
                @events
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
              # Get's (and sets) the array of callbacks
         | 
| 24 | 
            +
              # @return the array of callbacks
         | 
| 25 | 
            +
              def callbacks
         | 
| 26 | 
            +
                @callbacks ||= StateMachine.machines[self.class].callbacks
         | 
| 27 | 
            +
                @callbacks
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
              # Get's all the possible events you can perform
         | 
| 31 | 
            +
              # @return any event that you can perform given your state
         | 
| 32 | 
            +
              def possible_events
         | 
| 33 | 
            +
                pos = Array.new
         | 
| 34 | 
            +
                events.each_value{|event| pos << event if event.transitions.key?(current_state.name)}
         | 
| 35 | 
            +
                pos
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
            end
         | 
    
        data/lib/finite/machine.rb
    CHANGED
    
    | @@ -1,5 +1,121 @@ | |
| 1 1 | 
             
            module Finite
         | 
| 2 | 
            -
              class  | 
| 3 | 
            -
             | 
| 2 | 
            +
              # The State Machine class. Represents the whole state machine
         | 
| 3 | 
            +
              class StateMachine
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                class << self
         | 
| 6 | 
            +
                  attr_accessor :machines
         | 
| 7 | 
            +
                end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                attr_reader :states, :initial, :events, :callbacks
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                # Create a new state machine
         | 
| 12 | 
            +
                #
         | 
| 13 | 
            +
                # @param initial_state [Symbol] the initial state of this state machine
         | 
| 14 | 
            +
                # @param klass [Class] the class of the state machine
         | 
| 15 | 
            +
                # @param block [Block] the block of code that creates it
         | 
| 16 | 
            +
                def initialize(initial_state, klass, &block)
         | 
| 17 | 
            +
                  @class = klass
         | 
| 18 | 
            +
                  @initial = initial_state
         | 
| 19 | 
            +
                  @states = Hash.new
         | 
| 20 | 
            +
                  @events = Hash.new
         | 
| 21 | 
            +
                  @callbacks = {before: Hash.new , after: Hash.new}
         | 
| 22 | 
            +
                  instance_eval &block
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                # Add an event to the state machine
         | 
| 26 | 
            +
                #
         | 
| 27 | 
            +
                # @param event_name [Symbol] the event you are trying to add
         | 
| 28 | 
            +
                # @param block [Block] the block of code that creates an event
         | 
| 29 | 
            +
                # @raise [Exception] if the event already exists
         | 
| 30 | 
            +
                def add_event(event_name, &block)
         | 
| 31 | 
            +
                  # We don't want to randomly override things that we shouldn't
         | 
| 32 | 
            +
                  raise "Method already taken can_#{event_name}?" if @class.methods.include?(:"can_#{event_name}?")
         | 
| 33 | 
            +
                  raise "Method already taken #{event_name}" if @class.methods.include?(:"#{event_name}")
         | 
| 34 | 
            +
                  raise 'Event #{event_name} already exists. Rename or combine the events' if events.include? event_name
         | 
| 35 | 
            +
                  event = Event.new(event_name, &block)
         | 
| 36 | 
            +
                  @events[event_name] = event
         | 
| 37 | 
            +
                  event.transitions.each_value do |transition|
         | 
| 38 | 
            +
                    add_state transition.to
         | 
| 39 | 
            +
                    add_state transition.from
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
                  @class.send(:define_method, :"can_#{event_name}?") do
         | 
| 42 | 
            +
                    event.transitions.key? current_state.name
         | 
| 43 | 
            +
                  end
         | 
| 44 | 
            +
                  @class.send(:define_method, :"#{event_name}") do
         | 
| 45 | 
            +
                    if event.transitions.key? current_state.name
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                      event.callbacks[:before].each do |callback|
         | 
| 48 | 
            +
                        self.instance_eval &callback
         | 
| 49 | 
            +
                      end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                      if callbacks[:before].key? :all
         | 
| 52 | 
            +
                        callbacks[:before][:all].each do |callback|
         | 
| 53 | 
            +
                          self.instance_eval &callback
         | 
| 54 | 
            +
                        end
         | 
| 55 | 
            +
                      end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                      new_state = states[event.transitions[current_state.name].to]
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                      if callbacks[:before].key? new_state.name
         | 
| 60 | 
            +
                        callbacks[:before][new_state.name].each do |callback|
         | 
| 61 | 
            +
                          self.instance_eval &callback
         | 
| 62 | 
            +
                        end
         | 
| 63 | 
            +
                      end
         | 
| 64 | 
            +
                      @current_state = new_state
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                      if callbacks[:after].key? :all
         | 
| 67 | 
            +
                        callbacks[:after][:all].each do |callback|
         | 
| 68 | 
            +
                          self.instance_eval &callback
         | 
| 69 | 
            +
                        end
         | 
| 70 | 
            +
                      end
         | 
| 71 | 
            +
                      if callbacks[:after].key? current_state.name
         | 
| 72 | 
            +
                        callbacks[:after][current_state.name].each do |callback|
         | 
| 73 | 
            +
                          self.instance_eval &callback
         | 
| 74 | 
            +
                        end
         | 
| 75 | 
            +
                      end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                      event.callbacks[:after].each do |callback|
         | 
| 78 | 
            +
                        self.instance_eval &callback
         | 
| 79 | 
            +
                      end
         | 
| 80 | 
            +
                    else
         | 
| 81 | 
            +
                      raise 'Invalid Transition'
         | 
| 82 | 
            +
                    end
         | 
| 83 | 
            +
                  end
         | 
| 84 | 
            +
                end
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                # Add a state to the the state machine if the state hasn't already been
         | 
| 87 | 
            +
                # created
         | 
| 88 | 
            +
                #
         | 
| 89 | 
            +
                # @param state [Symbol] the state you are trying to add
         | 
| 90 | 
            +
                def add_state(state)
         | 
| 91 | 
            +
                  if not @states.include? state
         | 
| 92 | 
            +
                    # Prevents arbitrarily overriding methods that you shouldn't be
         | 
| 93 | 
            +
                    raise "Method already taken #{state}?" if @class.methods.include?(:"#{state}?")
         | 
| 94 | 
            +
                    @states[state] = State.new(state)
         | 
| 95 | 
            +
                    @class.send(:define_method, :"#{state}?"){current_state == state}
         | 
| 96 | 
            +
                  end
         | 
| 97 | 
            +
                end
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                private
         | 
| 100 | 
            +
                # The event method for the dsl
         | 
| 101 | 
            +
                #
         | 
| 102 | 
            +
                # @param name [Symbol] the name of the event
         | 
| 103 | 
            +
                # @param block [Block] the block of code that creates events
         | 
| 104 | 
            +
                def event(name, &block)
         | 
| 105 | 
            +
                  add_event name, &block
         | 
| 106 | 
            +
                end
         | 
| 107 | 
            +
             | 
| 108 | 
            +
                # Create the callback methods
         | 
| 109 | 
            +
                [:after, :before].each do |callback|
         | 
| 110 | 
            +
                  define_method callback do |*args, &block|
         | 
| 111 | 
            +
                    if args.count > 0
         | 
| 112 | 
            +
                      callbacks[callback][args[0]] ||= Array.new
         | 
| 113 | 
            +
                      callbacks[callback][args[0]] << block
         | 
| 114 | 
            +
                    else
         | 
| 115 | 
            +
                      callbacks[callback][:all] ||= Array.new
         | 
| 116 | 
            +
                      callbacks[callback][:all] << block
         | 
| 117 | 
            +
                    end
         | 
| 118 | 
            +
                  end
         | 
| 119 | 
            +
                end
         | 
| 4 120 | 
             
              end
         | 
| 5 121 | 
             
            end
         | 
    
        data/lib/finite/state.rb
    CHANGED
    
    | @@ -1,5 +1,38 @@ | |
| 1 1 | 
             
            module Finite
         | 
| 2 | 
            -
             | 
| 3 | 
            -
             | 
| 4 | 
            -
             | 
| 2 | 
            +
             | 
| 3 | 
            +
              # The State class. Represents a state in the state machine.
         | 
| 4 | 
            +
              class State
         | 
| 5 | 
            +
                attr_reader :name
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                # Create a new state
         | 
| 8 | 
            +
                #
         | 
| 9 | 
            +
                # @param name [Symbol] the name of the state
         | 
| 10 | 
            +
                def initialize(name)
         | 
| 11 | 
            +
                  @name = name
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                # Overide the == method for state
         | 
| 15 | 
            +
                #
         | 
| 16 | 
            +
                # @param state [Object] the state your comparing to
         | 
| 17 | 
            +
                # @return true if they are equal false if not
         | 
| 18 | 
            +
                def ==(state)
         | 
| 19 | 
            +
                  if state.is_a? Symbol
         | 
| 20 | 
            +
                    @name == state
         | 
| 21 | 
            +
                  elsif state.is_a? State
         | 
| 22 | 
            +
                    @name == state.name
         | 
| 23 | 
            +
                  else
         | 
| 24 | 
            +
                    false
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                # overrriden for puts and print
         | 
| 29 | 
            +
                def to_s
         | 
| 30 | 
            +
                  @name.to_s
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                # Overridden for p
         | 
| 34 | 
            +
                def inspect
         | 
| 35 | 
            +
                  @name
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
              end
         | 
| 5 38 | 
             
            end
         | 
    
        data/lib/finite/transition.rb
    CHANGED
    
    | @@ -1,5 +1,24 @@ | |
| 1 1 | 
             
            module Finite
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              # The transition class. Represents a transition between two states
         | 
| 2 4 | 
             
              class Transition
         | 
| 3 | 
            -
             | 
| 5 | 
            +
             | 
| 6 | 
            +
                attr_reader :to, :from
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                # Create a new transition object
         | 
| 9 | 
            +
                #
         | 
| 10 | 
            +
                # @param opts [Hash] the options for a transition. Include :to and :from
         | 
| 11 | 
            +
                def initialize(opts)
         | 
| 12 | 
            +
                  @from = opts[:from]
         | 
| 13 | 
            +
                  @to = opts[:to]
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                # Does this transition equal another transition?
         | 
| 17 | 
            +
                #
         | 
| 18 | 
            +
                # @param other [Transition] another transition
         | 
| 19 | 
            +
                # @return true if they are equal false if not
         | 
| 20 | 
            +
                def ==(other)
         | 
| 21 | 
            +
                  from == other.from and to == other.to
         | 
| 22 | 
            +
                end
         | 
| 4 23 | 
             
              end
         | 
| 5 24 | 
             
            end
         | 
    
        data/lib/finite/version.rb
    CHANGED
    
    
    
        data/lib/finite.rb
    CHANGED
    
    | @@ -1,5 +1,19 @@ | |
| 1 | 
            -
             | 
| 1 | 
            +
            [
         | 
| 2 | 
            +
              'version',
         | 
| 3 | 
            +
              'transition',
         | 
| 4 | 
            +
              'event',
         | 
| 5 | 
            +
              'state',
         | 
| 6 | 
            +
              'machine',
         | 
| 7 | 
            +
              'class_methods',
         | 
| 8 | 
            +
              'finite'
         | 
| 9 | 
            +
            ].each { |file| require File.join(File.dirname(__FILE__), 'finite', file) }
         | 
| 2 10 |  | 
| 11 | 
            +
            # The Finite module. The module that contains all the classes and methods for
         | 
| 12 | 
            +
            # the finite gem.
         | 
| 3 13 | 
             
            module Finite
         | 
| 4 | 
            -
              #  | 
| 5 | 
            -
             | 
| 14 | 
            +
              # Override included method
         | 
| 15 | 
            +
              def self.included(base)
         | 
| 16 | 
            +
                base.extend(ClassMethods)
         | 
| 17 | 
            +
                super
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
            end
         | 
| @@ -0,0 +1,59 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Elevator do
         | 
| 4 | 
            +
              before(:each) do
         | 
| 5 | 
            +
                @elevator = Elevator.new
         | 
| 6 | 
            +
              end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              it 'has a state machine' do
         | 
| 9 | 
            +
                expect(Finite::StateMachine.machines[Elevator]).to_not be_nil
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              context 'states' do
         | 
| 13 | 
            +
                it 'has a current state' do
         | 
| 14 | 
            +
                  expect(@elevator.current_state).to_not be_nil
         | 
| 15 | 
            +
                  expect(@elevator.current_state).to eq(:idle)
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                it 'has methods to tell whether it is in a state or not' do
         | 
| 19 | 
            +
                  expect(@elevator.idle?).to be_true
         | 
| 20 | 
            +
                  expect(@elevator.moving?).to be_false
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                it 'can access all states' do
         | 
| 24 | 
            +
                  expect(@elevator.states).to_not be_nil
         | 
| 25 | 
            +
                  expect(@elevator.states.count).to be(9)
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
              context 'events' do
         | 
| 30 | 
            +
                it 'can access all events' do
         | 
| 31 | 
            +
                  expect(@elevator.events).to_not be_nil
         | 
| 32 | 
            +
                  expect(@elevator.events.count).to be(10)
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                it 'can access possible events for a given state' do
         | 
| 36 | 
            +
                  expect(@elevator.possible_events).to eq([:prepare])
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                it 'has methods to tell whether an event can be performed' do
         | 
| 40 | 
            +
                  expect(@elevator.can_prepare?).to be_true
         | 
| 41 | 
            +
                  expect(@elevator.can_go_up?).to be_false
         | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                it 'can perform events' do
         | 
| 45 | 
            +
                  @elevator.prepare
         | 
| 46 | 
            +
                  expect(@elevator.current_state).to eq(:doors_closing)
         | 
| 47 | 
            +
                  expect(@elevator.doors_closing?).to be_true
         | 
| 48 | 
            +
                  expect(@elevator.idle?).to be_false
         | 
| 49 | 
            +
                  expect(@elevator.possible_events).to eq([:go_up,:go_down])
         | 
| 50 | 
            +
                  expect{@elevator.start}.to raise_error
         | 
| 51 | 
            +
                  @elevator.go_down
         | 
| 52 | 
            +
                  expect(@elevator.can_start?).to be_true
         | 
| 53 | 
            +
                  @elevator.start
         | 
| 54 | 
            +
                  @elevator.approach
         | 
| 55 | 
            +
                  @elevator.stop
         | 
| 56 | 
            +
                end
         | 
| 57 | 
            +
              end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
            end
         | 
    
        data/spec/event_spec.rb
    ADDED
    
    | @@ -0,0 +1,64 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Finite::Event do
         | 
| 4 | 
            +
              before(:each) do
         | 
| 5 | 
            +
                @block = Proc.new do
         | 
| 6 | 
            +
                  go from: :state1, to: :state2
         | 
| 7 | 
            +
                  after do
         | 
| 8 | 
            +
                    'hello again'
         | 
| 9 | 
            +
                  end
         | 
| 10 | 
            +
                  before do
         | 
| 11 | 
            +
                    'hello for the first time'
         | 
| 12 | 
            +
                  end
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              it 'has a name' do
         | 
| 17 | 
            +
                event = Finite::Event.new(:event1, &@block)
         | 
| 18 | 
            +
                expect(event.name).to eq(:event1)
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              context 'equality' do
         | 
| 22 | 
            +
                it 'equals symbols that have the same name' do
         | 
| 23 | 
            +
                  event = Finite::Event.new(:event1, &@block)
         | 
| 24 | 
            +
                  expect(event).to eq(:event1)
         | 
| 25 | 
            +
                  expect(event).not_to eq(:event2)
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                it 'equals events with the same name' do
         | 
| 29 | 
            +
                  event1 = Finite::Event.new(:event1, &@block)
         | 
| 30 | 
            +
                  event2 = Finite::Event.new(:event2, &@block)
         | 
| 31 | 
            +
                  event3 = Finite::Event.new(:event1, &@block)
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                  expect(event1).to eq(event3)
         | 
| 34 | 
            +
                  expect(event1).not_to eq(event2)
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                it "doesn't equal things that aren't symbols or events" do
         | 
| 38 | 
            +
                  event = Finite::Event.new(:event1, &@block)
         | 
| 39 | 
            +
                  expect(event).not_to eq('string')
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
              end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
              it 'should create transitions' do
         | 
| 44 | 
            +
                event = Finite::Event.new(:event1, &@block)
         | 
| 45 | 
            +
                event.transitions.count.should be(1)
         | 
| 46 | 
            +
                event.transitions[:state1].to.should eq(:state2)
         | 
| 47 | 
            +
                event.transitions[:state1].from.should eq(:state1)
         | 
| 48 | 
            +
              end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
              it 'should create callbacks' do
         | 
| 51 | 
            +
                event = Finite::Event.new(:event1, &@block)
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                expect(event.callbacks[:before]).not_to be_nil
         | 
| 54 | 
            +
                expect(event.callbacks[:after]).not_to be_nil
         | 
| 55 | 
            +
                expect(event.callbacks[:after][0].call).to eq('hello again')
         | 
| 56 | 
            +
                expect(event.callbacks[:before][0].call).to eq('hello for the first time')
         | 
| 57 | 
            +
              end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
              it 'has to_s and inspect methods' do
         | 
| 60 | 
            +
                event = Finite::Event.new(:event, &@block)
         | 
| 61 | 
            +
                expect(event.to_s).to eq('event')
         | 
| 62 | 
            +
                expect(event.inspect).to eq(:event)
         | 
| 63 | 
            +
              end
         | 
| 64 | 
            +
            end
         | 
| @@ -0,0 +1,67 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Finite::StateMachine do
         | 
| 4 | 
            +
              before(:each) do
         | 
| 5 | 
            +
                @elevator = Elevator.new
         | 
| 6 | 
            +
                @machine = Finite::StateMachine.machines[Elevator]
         | 
| 7 | 
            +
              end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              context 'adding events' do
         | 
| 10 | 
            +
                it 'has events' do
         | 
| 11 | 
            +
                  expect(@machine.events.count).to be(10)
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                it 'cannot have events with the same name' do
         | 
| 15 | 
            +
                  expect{@machine.add_event(:prepare){}}.to raise_error
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                it 'cannot be stupid with your event naming' do
         | 
| 19 | 
            +
                  expect{@machine.add_event(:to_s)}.to raise_error
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                it 'increases in size when an event is added' do
         | 
| 23 | 
            +
                  @machine.add_event(:random_event){}
         | 
| 24 | 
            +
                  expect(@machine.events.count).to be(11)
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
                it 'adds the proper helper methods' do
         | 
| 27 | 
            +
                  expect(@elevator.methods).to include(:random_event)
         | 
| 28 | 
            +
                  expect(@elevator.methods).to include(:can_random_event?)
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              context 'adding states' do
         | 
| 33 | 
            +
                it 'has states' do
         | 
| 34 | 
            +
                  expect(@machine.states.count).to be(9)
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                it 'cannot be stupid with your state naming' do
         | 
| 38 | 
            +
                  expect{@machine.add_state(:const_defined){}}.to raise_error
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                it 'cannot have states with the same name' do
         | 
| 42 | 
            +
                  @machine.add_state(:doors_closing){}
         | 
| 43 | 
            +
                  expect(@machine.states.count).to be(9)
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                it 'increases in size when a state is added' do
         | 
| 47 | 
            +
                  @machine.add_state(:random_state){}
         | 
| 48 | 
            +
                  expect(@machine.states.count).to be(10)
         | 
| 49 | 
            +
                end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                it 'adds the proper helper method' do
         | 
| 52 | 
            +
                  expect(@elevator.methods).to include(:random_state?)
         | 
| 53 | 
            +
                end
         | 
| 54 | 
            +
              end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
              context 'callbacks' do
         | 
| 57 | 
            +
                it 'has after and before keys' do
         | 
| 58 | 
            +
                  expect(@machine.callbacks).to include(:before)
         | 
| 59 | 
            +
                  expect(@machine.callbacks).to include(:after)
         | 
| 60 | 
            +
                end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                it 'adds callbacks' do
         | 
| 63 | 
            +
                  expect(@machine.callbacks[:before]).to include(:doors_closing)
         | 
| 64 | 
            +
                  expect(@machine.callbacks[:before]).to include(:doors_opening)
         | 
| 65 | 
            +
                end
         | 
| 66 | 
            +
              end
         | 
| 67 | 
            +
            end
         | 
| @@ -0,0 +1,94 @@ | |
| 1 | 
            +
             | 
| 2 | 
            +
            class Elevator
         | 
| 3 | 
            +
              include Finite
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              def initialize
         | 
| 6 | 
            +
                @before_called = 0
         | 
| 7 | 
            +
                @after_called = 0
         | 
| 8 | 
            +
              end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              finite initial: :idle do
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                before :doors_closing do
         | 
| 13 | 
            +
                  puts 'Doors Closing!'
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                before :doors_opening do
         | 
| 17 | 
            +
                  puts 'Doors Opening!'
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                after :doors_closing do
         | 
| 21 | 
            +
                  puts "I'm no longer idle"
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                before do
         | 
| 25 | 
            +
                  @before_called += 1
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                after do
         | 
| 29 | 
            +
                  @after_called += 1
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
             | 
| 33 | 
            +
                event :prepare do
         | 
| 34 | 
            +
                  go from: :idle, to: :doors_closing
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                event :go_up do
         | 
| 38 | 
            +
                  go from: :doors_closing, to: :elevator_going_up
         | 
| 39 | 
            +
                  after do
         | 
| 40 | 
            +
                    puts 'Going Up!'
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                event :go_down do
         | 
| 45 | 
            +
                  go from: :doors_closing, to: :elevator_going_down
         | 
| 46 | 
            +
                  after do
         | 
| 47 | 
            +
                    puts 'Going Down!'
         | 
| 48 | 
            +
                  end
         | 
| 49 | 
            +
                end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                event :start do
         | 
| 52 | 
            +
                  go from: [:elevator_going_up, :elevator_going_down], to: :moving
         | 
| 53 | 
            +
                end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                event :approach do
         | 
| 56 | 
            +
                  go from: :moving, to: :stopping
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                event :stop do
         | 
| 60 | 
            +
                  go from: :stopping, to: :doors_opening
         | 
| 61 | 
            +
                  before do
         | 
| 62 | 
            +
                    announce_floor
         | 
| 63 | 
            +
                  end
         | 
| 64 | 
            +
                end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                event :open_doors do
         | 
| 67 | 
            +
                  go from: :doors_opening, to: :at_floor
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                event :finish do
         | 
| 71 | 
            +
                  go from: :at_floor, to: :checking_next_dest
         | 
| 72 | 
            +
                end
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                event :make_request do
         | 
| 75 | 
            +
                  go from: :checking_next_dest, to: :doors_closing
         | 
| 76 | 
            +
                end
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                event :make_no_request do
         | 
| 79 | 
            +
                  go from: :checking_next_dest, to: :idle
         | 
| 80 | 
            +
                end
         | 
| 81 | 
            +
              end
         | 
| 82 | 
            +
              def announce_floor
         | 
| 83 | 
            +
                puts "Arriving on floor #{rand(10)}"
         | 
| 84 | 
            +
              end
         | 
| 85 | 
            +
            end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
            # elevator = Elevator.new
         | 
| 88 | 
            +
            # elevator.prepare
         | 
| 89 | 
            +
            # elevator.go_up
         | 
| 90 | 
            +
            # elevator.start
         | 
| 91 | 
            +
            # elevator.approach
         | 
| 92 | 
            +
            # elevator.stop
         | 
| 93 | 
            +
            # puts elevator.can_open_doors?
         | 
| 94 | 
            +
            # puts elevator.can_finish?
         | 
    
        data/spec/spec_helper.rb
    ADDED
    
    | @@ -0,0 +1,20 @@ | |
| 1 | 
            +
            require 'rspec'
         | 
| 2 | 
            +
            require 'simplecov'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            SimpleCov.start
         | 
| 5 | 
            +
            require File.join(File.dirname(__FILE__), '..', 'lib', 'finite')
         | 
| 6 | 
            +
            Dir[File.dirname(__FILE__) + "/models/*.rb"].sort.each { |f| require File.expand_path(f) }
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            RSpec.configure do |config|
         | 
| 9 | 
            +
              original_stderr = $stderr
         | 
| 10 | 
            +
              original_stdout = $stdout
         | 
| 11 | 
            +
              config.before(:all) do
         | 
| 12 | 
            +
                # Redirect stderr and stdout
         | 
| 13 | 
            +
                $stderr = File.new(File.join(File.dirname(__FILE__), 'null.txt'), 'w')
         | 
| 14 | 
            +
                $stdout = File.new(File.join(File.dirname(__FILE__), 'null.txt'), 'w')
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
              config.after(:all) do
         | 
| 17 | 
            +
                $stderr = original_stderr
         | 
| 18 | 
            +
                $stdout = original_stdout
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
            end
         | 
    
        data/spec/state_spec.rb
    ADDED
    
    | @@ -0,0 +1,36 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Finite::State do
         | 
| 4 | 
            +
              before(:each) do
         | 
| 5 | 
            +
                @name = :state_name
         | 
| 6 | 
            +
              end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              it 'has a name' do
         | 
| 9 | 
            +
                Finite::State.new(@name).name.should eq(:state_name)
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
              context 'equality' do
         | 
| 12 | 
            +
                it 'equals a symbol of the same name' do
         | 
| 13 | 
            +
                  state = Finite::State.new(@name)
         | 
| 14 | 
            +
                  expect(state).to eq(:state_name)
         | 
| 15 | 
            +
                  expect(state).not_to eq(:different_name)
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                it 'equals a state with the same name' do
         | 
| 19 | 
            +
                  state1 = Finite::State.new(@name)
         | 
| 20 | 
            +
                  state2 = Finite::State.new(:different_name)
         | 
| 21 | 
            +
                  state3 = Finite::State.new(@name)
         | 
| 22 | 
            +
                  expect(state1).to eq(state3)
         | 
| 23 | 
            +
                  expect(state1).not_to eq(state2)
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                it "doesn't equal objects that aren't states or symbols" do
         | 
| 27 | 
            +
                  state = Finite::State.new(@name)
         | 
| 28 | 
            +
                  expect(state).not_to eq('string')
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
              it 'has to_s and inspect methods' do
         | 
| 32 | 
            +
                state = Finite::State.new(@name)
         | 
| 33 | 
            +
                expect(state.to_s).to eq('state_name')
         | 
| 34 | 
            +
                expect(state.inspect).to eq(:state_name)
         | 
| 35 | 
            +
              end
         | 
| 36 | 
            +
            end
         | 
| @@ -0,0 +1,20 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Finite::Transition do
         | 
| 4 | 
            +
              it 'has a to and a from' do
         | 
| 5 | 
            +
                transition = Finite::Transition.new({from: :state1, to: :state2})
         | 
| 6 | 
            +
                expect(transition.from).to eq(:state1)
         | 
| 7 | 
            +
                expect(transition.to).to eq(:state2)
         | 
| 8 | 
            +
              end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              it 'equals transitions with the same to and from' do
         | 
| 11 | 
            +
                transition1 = Finite::Transition.new({from: :state1, to: :state2})
         | 
| 12 | 
            +
                transition2 = Finite::Transition.new({from: :state1, to: :state3})
         | 
| 13 | 
            +
                transition3 = Finite::Transition.new({from: :state4, to: :state2})
         | 
| 14 | 
            +
                transition4 = Finite::Transition.new({from: :state1, to: :state2})
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                expect(transition1).not_to eq(transition2)
         | 
| 17 | 
            +
                expect(transition1).not_to eq(transition3)
         | 
| 18 | 
            +
                expect(transition1).to eq(transition4)
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: finite
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.0 | 
| 4 | 
            +
              version: 1.0.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Kristen Mills
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2013- | 
| 11 | 
            +
            date: 2013-07-31 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: bundler
         | 
| @@ -38,6 +38,48 @@ dependencies: | |
| 38 38 | 
             
                - - '>='
         | 
| 39 39 | 
             
                  - !ruby/object:Gem::Version
         | 
| 40 40 | 
             
                    version: '0'
         | 
| 41 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 42 | 
            +
              name: simplecov
         | 
| 43 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 44 | 
            +
                requirements:
         | 
| 45 | 
            +
                - - '>='
         | 
| 46 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 47 | 
            +
                    version: '0'
         | 
| 48 | 
            +
              type: :development
         | 
| 49 | 
            +
              prerelease: false
         | 
| 50 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 51 | 
            +
                requirements:
         | 
| 52 | 
            +
                - - '>='
         | 
| 53 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 54 | 
            +
                    version: '0'
         | 
| 55 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 56 | 
            +
              name: rspec
         | 
| 57 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 58 | 
            +
                requirements:
         | 
| 59 | 
            +
                - - '>='
         | 
| 60 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 61 | 
            +
                    version: '0'
         | 
| 62 | 
            +
              type: :development
         | 
| 63 | 
            +
              prerelease: false
         | 
| 64 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 65 | 
            +
                requirements:
         | 
| 66 | 
            +
                - - '>='
         | 
| 67 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 68 | 
            +
                    version: '0'
         | 
| 69 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 70 | 
            +
              name: yard
         | 
| 71 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 72 | 
            +
                requirements:
         | 
| 73 | 
            +
                - - '>='
         | 
| 74 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 75 | 
            +
                    version: '0'
         | 
| 76 | 
            +
              type: :development
         | 
| 77 | 
            +
              prerelease: false
         | 
| 78 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 79 | 
            +
                requirements:
         | 
| 80 | 
            +
                - - '>='
         | 
| 81 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 82 | 
            +
                    version: '0'
         | 
| 41 83 | 
             
            description: A simple state machine implementation for ruby
         | 
| 42 84 | 
             
            email:
         | 
| 43 85 | 
             
            - kristen@kristen-mills.com
         | 
| @@ -46,17 +88,27 @@ extensions: [] | |
| 46 88 | 
             
            extra_rdoc_files: []
         | 
| 47 89 | 
             
            files:
         | 
| 48 90 | 
             
            - .gitignore
         | 
| 91 | 
            +
            - .travis.yml
         | 
| 49 92 | 
             
            - Gemfile
         | 
| 50 93 | 
             
            - LICENSE.txt
         | 
| 51 94 | 
             
            - README.md
         | 
| 52 95 | 
             
            - Rakefile
         | 
| 53 96 | 
             
            - finite.gemspec
         | 
| 54 97 | 
             
            - lib/finite.rb
         | 
| 98 | 
            +
            - lib/finite/class_methods.rb
         | 
| 55 99 | 
             
            - lib/finite/event.rb
         | 
| 100 | 
            +
            - lib/finite/finite.rb
         | 
| 56 101 | 
             
            - lib/finite/machine.rb
         | 
| 57 102 | 
             
            - lib/finite/state.rb
         | 
| 58 103 | 
             
            - lib/finite/transition.rb
         | 
| 59 104 | 
             
            - lib/finite/version.rb
         | 
| 105 | 
            +
            - spec/elevator_spec.rb
         | 
| 106 | 
            +
            - spec/event_spec.rb
         | 
| 107 | 
            +
            - spec/machine_spec.rb
         | 
| 108 | 
            +
            - spec/models/elevator.rb
         | 
| 109 | 
            +
            - spec/spec_helper.rb
         | 
| 110 | 
            +
            - spec/state_spec.rb
         | 
| 111 | 
            +
            - spec/transition_spec.rb
         | 
| 60 112 | 
             
            homepage: http://github.com/kristenmills/finite
         | 
| 61 113 | 
             
            licenses:
         | 
| 62 114 | 
             
            - MIT
         | 
| @@ -81,4 +133,12 @@ rubygems_version: 2.0.3 | |
| 81 133 | 
             
            signing_key: 
         | 
| 82 134 | 
             
            specification_version: 4
         | 
| 83 135 | 
             
            summary: A simple state machine implementation for ruby
         | 
| 84 | 
            -
            test_files: | 
| 136 | 
            +
            test_files:
         | 
| 137 | 
            +
            - spec/elevator_spec.rb
         | 
| 138 | 
            +
            - spec/event_spec.rb
         | 
| 139 | 
            +
            - spec/machine_spec.rb
         | 
| 140 | 
            +
            - spec/models/elevator.rb
         | 
| 141 | 
            +
            - spec/spec_helper.rb
         | 
| 142 | 
            +
            - spec/state_spec.rb
         | 
| 143 | 
            +
            - spec/transition_spec.rb
         | 
| 144 | 
            +
            has_rdoc: 
         |