finite 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: efb775ca43d0ce5dddd4215fde0c54b5f764e097
4
- data.tar.gz: f617e7113c8f30f590c353dfa664776e74cb6c32
3
+ metadata.gz: e38ef2b1b5515d6ae12b8fba4f0e5c6a96e497bc
4
+ data.tar.gz: 406818e0855c7fabe2b6400702f1a5a84517696a
5
5
  SHA512:
6
- metadata.gz: 7e6a27d3620e1ed8a3d80099d9ff9ae7ac693ac04a81ba570b6048565e9cc6d94cd4a7ff69e5944489d652aec55ace9cabc9b688ae60d64e6c6d37762352f3e0
7
- data.tar.gz: ad0e60854b2334e045f78c35e0649e610e56abb9253ed0f22c6260972a8b469206e385052a1748dccc23ef84d7602bee120b44aafd2488aa6ab61f0583197d80
6
+ metadata.gz: a90dc4be0bf9b90267fe93a7d5f03af3eb032451032ff6a758a05ef3348cf9bf2042eef00bdacfe13a9ddc200c1c4682dcb9d2f5d325f9f4ba36002d92a21efc
7
+ data.tar.gz: 662f8bcc2153fed063d61866abbcd1388b965b94ab52ac5d3646238b874e533fd6dd1a173b719d530d35b2ed4e12494bfe189ff053e88fabcb0356f3b106a8d6
data/.gitignore CHANGED
@@ -15,4 +15,3 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
- spec/null.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/.travis.yml CHANGED
@@ -1,6 +1,5 @@
1
1
  language: ruby
2
2
  rvm:
3
+ - 2.1.0
3
4
  - 2.0.0
4
- - 1.9.3
5
- - jruby-19mode # JRuby in 1.9 mode
6
- - rbx-19mode
5
+ - 1.9.3
data/README.md CHANGED
@@ -19,14 +19,19 @@ Or install it yourself as:
19
19
 
20
20
  ## Usage
21
21
  ```ruby
22
+ require 'finite'
22
23
 
23
24
  class Elevator
24
25
  include Finite
25
26
 
27
+ def initialize
28
+ @broken = false
29
+ end
30
+
26
31
  finite initial: :idle do
27
32
 
28
33
  before do
29
- "This is called before every state but has no purpose other than to show it's existence in this example."
34
+ "This is called before every state but has no purpose other than to show its existence in this example."
30
35
  end
31
36
 
32
37
  before :doors_closing do
@@ -38,7 +43,7 @@ class Elevator
38
43
  end
39
44
 
40
45
  event :prepare do
41
- go from: :idle, to: :doors_closing
46
+ go from: :idle, to: :doors_closing, if: -> { not @broken }
42
47
  end
43
48
 
44
49
  event :go_up do
@@ -98,7 +103,7 @@ elevator = Elevator.new
98
103
  elevator.current_state # => :idle
99
104
  elevator.can_prepare? # => true
100
105
  elevator.can_open_doors? # => false
101
- elevator.open_doors # => RuntimeError 'Invalid Transition'
106
+ elevator.open_doors # => Finite::Error 'Invalid Transition'
102
107
  elevator.idle? # => true
103
108
  elevator.prepare # => 'Doors Closing!'
104
109
  elevator.current_state # => :doors_closing
@@ -114,7 +119,7 @@ elevator.possible_events # => [:go_up, :go_down]
114
119
  5. Create new Pull Request
115
120
 
116
121
  ## License
117
- Copyright (c) 2013 Kristen Mills
122
+ Copyright (c) 2014 Kristen Mills
118
123
 
119
124
  MIT License
120
125
 
@@ -135,4 +140,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
135
140
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
136
141
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
137
142
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
138
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
143
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/finite.gemspec CHANGED
@@ -21,6 +21,6 @@ Gem::Specification.new do |spec|
21
21
  spec.add_development_dependency "bundler", "~> 1.3"
22
22
  spec.add_development_dependency "rake"
23
23
  spec.add_development_dependency "simplecov"
24
- spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "rspec", '~>3.0'
25
25
  spec.add_development_dependency "yard"
26
26
  end
data/lib/finite.rb CHANGED
@@ -16,4 +16,4 @@ module Finite
16
16
  base.extend(ClassMethods)
17
17
  super
18
18
  end
19
- end
19
+ end
data/lib/finite/event.rb CHANGED
@@ -30,7 +30,7 @@ module Finite
30
30
  end
31
31
  end
32
32
 
33
- # overrriden for puts and print
33
+ # Overridden for puts and print
34
34
  def to_s
35
35
  @name.to_s
36
36
  end
@@ -40,29 +40,29 @@ module Finite
40
40
  @name
41
41
  end
42
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]}
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)
52
58
  end
53
- else
54
- options << opts
55
- end
56
- options.each do |opt|
57
- @transitions[opt[:from]] = Transition.new(opt)
58
59
  end
59
- end
60
60
 
61
- # Create the callback methods
62
- [:after, :before].each do |callback|
63
- define_method callback do |*args, &block|
64
- @callbacks[callback] << block
61
+ # Create the callback methods
62
+ [:after, :before].each do |callback|
63
+ define_method callback do |*args, &block|
64
+ @callbacks[callback] << block
65
+ end
65
66
  end
66
- end
67
67
  end
68
68
  end
@@ -34,51 +34,70 @@ module Finite
34
34
  raise 'Event #{event_name} already exists. Rename or combine the events' if events.include? event_name
35
35
  event = Event.new(event_name, &block)
36
36
  @events[event_name] = event
37
+
38
+ # Add the states from the transition
37
39
  event.transitions.each_value do |transition|
38
40
  add_state transition.to
39
41
  add_state transition.from
40
42
  end
43
+
44
+ # Creates the method can_event_name?
41
45
  @class.send(:define_method, :"can_#{event_name}?") do
42
46
  event.transitions.key? current_state.name
43
47
  end
48
+
49
+ # Creates the method event_name
44
50
  @class.send(:define_method, :"#{event_name}") do
45
51
  if event.transitions.key? current_state.name
46
52
 
47
- event.callbacks[:before].each do |callback|
48
- self.instance_eval &callback
49
- end
53
+ # Makes sure the transition can happen
54
+ transition = event.transitions[current_state.name]
55
+ if transition.condition.nil? or self.instance_exec(&transition.condition)
56
+
57
+ new_state = states[event.transitions[current_state.name].to]
50
58
 
51
- if callbacks[:before].key? :all
52
- callbacks[:before][:all].each do |callback|
59
+ # Call all of the "before event" callbacks
60
+ event.callbacks[:before].each do |callback|
53
61
  self.instance_eval &callback
54
62
  end
55
- end
56
63
 
57
- new_state = states[event.transitions[current_state.name].to]
64
+ # Call all of the before_all callbacks
65
+ if callbacks[:before].key? :all
66
+ callbacks[:before][:all].each do |callback|
67
+ self.instance_eval &callback
68
+ end
69
+ end
58
70
 
59
- if callbacks[:before].key? new_state.name
60
- callbacks[:before][new_state.name].each do |callback|
61
- self.instance_eval &callback
71
+ # Call the "before state" callbacks
72
+ if callbacks[:before].key? new_state.name
73
+ callbacks[:before][new_state.name].each do |callback|
74
+ self.instance_eval &callback
75
+ end
62
76
  end
63
- end
64
- @current_state = new_state
65
77
 
66
- if callbacks[:after].key? :all
67
- callbacks[:after][:all].each do |callback|
68
- self.instance_eval &callback
78
+ # Set the current state
79
+ @current_state = new_state
80
+
81
+ # call the "after state" callbacks
82
+ if callbacks[:after].key? current_state.name
83
+ callbacks[:after][current_state.name].each do |callback|
84
+ self.instance_eval &callback
85
+ end
69
86
  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
87
+
88
+ # call the "after all" callbacks
89
+ if callbacks[:after].key? :all
90
+ callbacks[:after][:all].each do |callback|
91
+ self.instance_eval &callback
92
+ end
74
93
  end
75
- end
76
94
 
77
- event.callbacks[:after].each do |callback|
78
- self.instance_eval &callback
95
+ # Call the "after event" callbacks
96
+ event.callbacks[:after].each do |callback|
97
+ self.instance_eval &callback
98
+ end
99
+ self
79
100
  end
80
- else
81
- raise 'Invalid Transition'
82
101
  end
83
102
  end
84
103
  end
@@ -118,4 +137,4 @@ module Finite
118
137
  end
119
138
  end
120
139
  end
121
- end
140
+ end
@@ -3,14 +3,15 @@ module Finite
3
3
  # The transition class. Represents a transition between two states
4
4
  class Transition
5
5
 
6
- attr_reader :to, :from
6
+ attr_reader :to, :from, :condition
7
7
 
8
8
  # Create a new transition object
9
9
  #
10
- # @param opts [Hash] the options for a transition. Include :to and :from
10
+ # @param opts [Hash] the options for a transition. Include :to, :from, and :if
11
11
  def initialize(opts)
12
12
  @from = opts[:from]
13
13
  @to = opts[:to]
14
+ @condition = opts[:if]
14
15
  end
15
16
 
16
17
  # Does this transition equal another transition?
@@ -18,7 +19,7 @@ module Finite
18
19
  # @param other [Transition] another transition
19
20
  # @return true if they are equal false if not
20
21
  def ==(other)
21
- from == other.from and to == other.to
22
+ from == other.from and to == other.to and condition == other.condition
22
23
  end
23
24
  end
24
25
  end
@@ -1,4 +1,4 @@
1
1
  module Finite
2
2
  # The version number
3
- VERSION = "1.0.0"
3
+ VERSION = "1.1.0"
4
4
  end
@@ -1,9 +1,8 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Elevator do
4
- before(:each) do
5
- @elevator = Elevator.new
6
- end
4
+
5
+ let(:elevator) { Elevator.new }
7
6
 
8
7
  it 'has a state machine' do
9
8
  expect(Finite::StateMachine.machines[Elevator]).to_not be_nil
@@ -11,49 +10,59 @@ describe Elevator do
11
10
 
12
11
  context 'states' do
13
12
  it 'has a current state' do
14
- expect(@elevator.current_state).to_not be_nil
15
- expect(@elevator.current_state).to eq(:idle)
13
+ expect(elevator.current_state).to_not be_nil
14
+ expect(elevator.current_state).to eq(:idle)
16
15
  end
17
16
 
18
17
  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
18
+ expect(elevator.idle?).to be true
19
+ expect(elevator.moving?).to be false
21
20
  end
22
21
 
23
22
  it 'can access all states' do
24
- expect(@elevator.states).to_not be_nil
25
- expect(@elevator.states.count).to be(9)
23
+ expect(elevator.states).to_not be_nil
24
+ expect(elevator.states.count).to be(9)
26
25
  end
27
26
  end
28
27
 
29
28
  context 'events' do
30
29
  it 'can access all events' do
31
- expect(@elevator.events).to_not be_nil
32
- expect(@elevator.events.count).to be(10)
30
+ expect(elevator.events).to_not be_nil
31
+ expect(elevator.events.count).to be(10)
33
32
  end
34
33
 
35
34
  it 'can access possible events for a given state' do
36
- expect(@elevator.possible_events).to eq([:prepare])
35
+ expect(elevator.possible_events).to eq([:prepare])
37
36
  end
38
37
 
39
38
  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
39
+ expect(elevator.can_prepare?).to be true
40
+ expect(elevator.can_go_up?).to be false
42
41
  end
43
42
 
44
43
  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
44
+ elevator.prepare
45
+ expect(elevator.current_state).to eq(:doors_closing)
46
+ expect(elevator.doors_closing?).to be true
47
+ expect(elevator.idle?).to be false
48
+ expect(elevator.possible_events).to eq([:go_up,:go_down])
49
+ elevator.start
50
+ expect(elevator.current_state).to eq(:doors_closing)
51
+ elevator.go_down
52
+ expect(elevator.can_start?).to be true
53
+ elevator.start
54
+ elevator.approach
55
+ elevator.stop
56
+ end
57
+
58
+ it 'will respond to conditions' do
59
+ elevator.broken = true
60
+ elevator.prepare
61
+ expect(elevator.current_state).to eq(:idle)
62
+ elevator.broken = false
63
+ elevator.prepare
64
+ expect(elevator.current_state).to eq(:doors_closing)
56
65
  end
57
66
  end
58
67
 
59
- end
68
+ end
data/spec/event_spec.rb CHANGED
@@ -42,9 +42,9 @@ describe Finite::Event do
42
42
 
43
43
  it 'should create transitions' do
44
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)
45
+ expect(event.transitions.count).to eql(1)
46
+ expect(event.transitions[:state1].to).to eq(:state2)
47
+ expect(event.transitions[:state1].from).to eq(:state1)
48
48
  end
49
49
 
50
50
  it 'should create callbacks' do
@@ -61,4 +61,4 @@ describe Finite::Event do
61
61
  expect(event.to_s).to eq('event')
62
62
  expect(event.inspect).to eq(:event)
63
63
  end
64
- end
64
+ end
@@ -1,10 +1,11 @@
1
1
 
2
2
  class Elevator
3
3
  include Finite
4
-
4
+ attr_accessor :broken
5
5
  def initialize
6
6
  @before_called = 0
7
7
  @after_called = 0
8
+ @broken = false
8
9
  end
9
10
 
10
11
  finite initial: :idle do
@@ -31,7 +32,7 @@ class Elevator
31
32
 
32
33
 
33
34
  event :prepare do
34
- go from: :idle, to: :doors_closing
35
+ go from: :idle, to: :doors_closing, if: -> { not @broken }
35
36
  end
36
37
 
37
38
  event :go_up do
@@ -91,4 +92,4 @@ end
91
92
  # elevator.approach
92
93
  # elevator.stop
93
94
  # puts elevator.can_open_doors?
94
- # puts elevator.can_finish?
95
+ # puts elevator.can_finish?
data/spec/spec_helper.rb CHANGED
@@ -10,11 +10,11 @@ RSpec.configure do |config|
10
10
  original_stdout = $stdout
11
11
  config.before(:all) do
12
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')
13
+ $stderr = StringIO.new
14
+ $stdout = StringIO.new
15
15
  end
16
16
  config.after(:all) do
17
17
  $stderr = original_stderr
18
18
  $stdout = original_stdout
19
19
  end
20
- end
20
+ end
data/spec/state_spec.rb CHANGED
@@ -6,7 +6,7 @@ describe Finite::State do
6
6
  end
7
7
 
8
8
  it 'has a name' do
9
- Finite::State.new(@name).name.should eq(:state_name)
9
+ expect(Finite::State.new(@name).name).to eq(:state_name)
10
10
  end
11
11
  context 'equality' do
12
12
  it 'equals a symbol of the same name' do
@@ -33,4 +33,4 @@ describe Finite::State do
33
33
  expect(state.to_s).to eq('state_name')
34
34
  expect(state.inspect).to eq(:state_name)
35
35
  end
36
- end
36
+ end
metadata CHANGED
@@ -1,83 +1,83 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: finite
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.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-07-31 00:00:00.000000000 Z
11
+ date: 2014-07-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.3'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.3'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: simplecov
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '>='
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '>='
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - '>='
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: '3.0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - '>='
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '0'
68
+ version: '3.0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: yard
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - '>='
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - '>='
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  description: A simple state machine implementation for ruby
@@ -87,8 +87,9 @@ executables: []
87
87
  extensions: []
88
88
  extra_rdoc_files: []
89
89
  files:
90
- - .gitignore
91
- - .travis.yml
90
+ - ".gitignore"
91
+ - ".rspec"
92
+ - ".travis.yml"
92
93
  - Gemfile
93
94
  - LICENSE.txt
94
95
  - README.md
@@ -119,17 +120,17 @@ require_paths:
119
120
  - lib
120
121
  required_ruby_version: !ruby/object:Gem::Requirement
121
122
  requirements:
122
- - - '>='
123
+ - - ">="
123
124
  - !ruby/object:Gem::Version
124
125
  version: '0'
125
126
  required_rubygems_version: !ruby/object:Gem::Requirement
126
127
  requirements:
127
- - - '>='
128
+ - - ">="
128
129
  - !ruby/object:Gem::Version
129
130
  version: '0'
130
131
  requirements: []
131
132
  rubyforge_project:
132
- rubygems_version: 2.0.3
133
+ rubygems_version: 2.2.0
133
134
  signing_key:
134
135
  specification_version: 4
135
136
  summary: A simple state machine implementation for ruby