end_state 0.1.0 → 0.2.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: b1d64ebcbb974d3190a824a6cf1c77742c009339
4
- data.tar.gz: 6acbeb81100f52bf97956a2bcbe7c5680bf02cba
3
+ metadata.gz: 04263dcaee90aaa630e9e16fd1648a71717b5c49
4
+ data.tar.gz: 1e5cba77cd2f71faa5792ba9374f7c14c941dda9
5
5
  SHA512:
6
- metadata.gz: 16a4bc9c85e10fce41a81659aa9bb70b182a3378030e2531f4b5077c2749cda53de5dec0b49e94862d6d71aaf698c047c5b5532dffd0079b5fc7dd459a4caf56
7
- data.tar.gz: 953922dc24b1bccd281564ee4769d515e45ef4fa4cd30d28c945368e2bba89defb92c6da22464ff8f83ecbaa96d5b1ec0b0bd689c32c8acd8f18d4e229d01f95
6
+ metadata.gz: f9e25308af4b71252f6e3709949077ffe7dee67312aea2eff0e310848b8f1215c2fa84f6259901ceee0a0560ee6e5dd6b6064c81720c87fc19cb1ce5a9962dd2
7
+ data.tar.gz: 4d9db32fc84ae115f6f6ae02e0a901f1f366351bc6291ae6c535f5633b12347fab002fb67322f627bb152f8084ff4c1e7adf773221fd4150b2f0fd01b5a7f979
data/Gemfile CHANGED
@@ -2,3 +2,4 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in end_state.gemspec
4
4
  gemspec
5
+ gem 'ruby-graphviz'
data/README.md CHANGED
@@ -77,7 +77,12 @@ These will only be called during the check performed during the transition and w
77
77
  These hooks can be useful for things like logging.
78
78
 
79
79
  The wrapped object has an array `failure_messages` available for tracking reasons for invalid transitions. You may shovel
80
- a reason (string) into this if you want to provide information on why your guard failed.
80
+ a reason (string) into this if you want to provide information on why your guard failed. You can also use the helper method in
81
+ the `Guard` class called `add_error` which takes a string.
82
+
83
+ The wrapped object has an array `success_messages` available for tracking reasons for valid transitions. You may shovel
84
+ a reason (string) into this if you want to provide information on why your guard passed. You can also use the helper method in
85
+ the `Guard` class called `add_success` which takes a string.
81
86
 
82
87
  ```ruby
83
88
  class EasyGuard < EndState::Guard
@@ -121,7 +126,12 @@ set up a little differently and you have access to:
121
126
  * `params` - A hash of params passed when calling transition on the machine.
122
127
 
123
128
  The wrapped object has an array `failure_messages` available for tracking reasons for invalid transitions. You may shovel
124
- a reason (string) into this if you want to provide information on why your finalizer failed.
129
+ a reason (string) into this if you want to provide information on why your finalizer failed. You can also use the helper method in
130
+ the `Finalizer` class called `add_error` which takes a string.
131
+
132
+ The wrapped object has an array `success_messages` available for tracking reasons for valid transitions. You may shovel
133
+ a reason (string) into this if you want to provide information on why your finalizer succeeded. You can also use the helper method in
134
+ the `Finalizer` class called `add_success` which takes a string.
125
135
 
126
136
  ```ruby
127
137
  class WrapUp < EndState::Finalizer
@@ -195,6 +205,12 @@ transition to the new state.
195
205
  You also have the option to use `transition!` which will instead raise an error for failures. If your guards and/or finalizers
196
206
  add to the `failure_messages` array then they will be included in the error message.
197
207
 
208
+ ## Graphing
209
+
210
+ If you install `GraphViz` and the gem `ruby-graphviz` you can create images representing your state machines.
211
+
212
+ `EndState::Graph.new(MyMachine).draw.output png: 'my_machine.png'`
213
+
198
214
  ## Testing
199
215
 
200
216
  Included is a custom RSpec matcher for testing your machines.
data/Rakefile CHANGED
@@ -4,3 +4,11 @@ require "rspec/core/rake_task"
4
4
  RSpec::Core::RakeTask.new(:spec)
5
5
 
6
6
  task :default => :spec
7
+
8
+ task :console do
9
+ require 'irb'
10
+ require 'irb/completion'
11
+ require 'end_state'
12
+ ARGV.clear
13
+ IRB.start
14
+ end
@@ -1,5 +1,6 @@
1
1
  module EndState
2
2
  class Finalizer
3
+ include Messages
3
4
  attr_reader :object, :state, :params
4
5
 
5
6
  def initialize(object, state, params)
@@ -0,0 +1,21 @@
1
+ module EndState
2
+ class Graph < GraphViz
3
+ attr_reader :machine, :nodes
4
+
5
+ def initialize(machine)
6
+ @machine = machine
7
+ @nodes = {}
8
+ super machine.name.to_sym
9
+ end
10
+
11
+ def draw
12
+ machine.transitions.keys.each do |t|
13
+ left, right = t.to_a.flatten
14
+ nodes[left] ||= add_node(left.to_s)
15
+ nodes[right] ||= add_node(right.to_s)
16
+ add_edge nodes[left], nodes[right]
17
+ end
18
+ self
19
+ end
20
+ end
21
+ end
@@ -1,5 +1,6 @@
1
1
  module EndState
2
2
  class Guard
3
+ include Messages
3
4
  attr_reader :object, :state, :params
4
5
 
5
6
  def initialize(object, state, params)
@@ -0,0 +1,11 @@
1
+ module EndState
2
+ module Messages
3
+ def add_error(message)
4
+ object.failure_messages << message
5
+ end
6
+
7
+ def add_success(message)
8
+ object.success_messages << message
9
+ end
10
+ end
11
+ end
@@ -1,6 +1,6 @@
1
1
  module EndState
2
2
  class StateMachine < SimpleDelegator
3
- attr_accessor :failure_messages
3
+ attr_accessor :failure_messages, :success_messages
4
4
 
5
5
  def self.transition(state_map)
6
6
  initial_states = Array(state_map.keys.first)
@@ -59,6 +59,7 @@ module EndState
59
59
 
60
60
  def transition(state, params = {}, mode = :soft)
61
61
  @failure_messages = []
62
+ @success_messages = []
62
63
  previous_state = self.state
63
64
  transition = self.class.transitions[{ previous_state => state }]
64
65
  return block_transistion(transition, state, mode) unless transition
@@ -1,3 +1,3 @@
1
1
  module EndState
2
- VERSION = '0.1.0'
2
+ VERSION = '0.2.0'
3
3
  end
data/lib/end_state.rb CHANGED
@@ -1,12 +1,18 @@
1
1
  require 'delegate'
2
2
  require 'end_state/version'
3
3
  require 'end_state/errors'
4
+ require 'end_state/messages'
4
5
  require 'end_state/guard'
5
6
  require 'end_state/finalizer'
6
7
  require 'end_state/finalizers'
7
8
  require 'end_state/transition'
8
9
  require 'end_state/action'
9
10
  require 'end_state/state_machine'
11
+ begin
12
+ require 'graphviz'
13
+ require 'end_state/graph'
14
+ rescue LoadError
15
+ end
10
16
 
11
17
  module EndState
12
18
  end
@@ -0,0 +1,14 @@
1
+ namespace :end_state do
2
+ desc 'Draw the statemachine using GraphViz (options: machine=MyMachine, format=png, output=machine.png'
3
+ task :draw do
4
+ options = {}
5
+ options[:machine] = ENV['machine']
6
+ options[:format] = ENV['format'] || :png
7
+ options[:output] = ENV['output'] || "#{options[:machine].to_s}.#{options[:format].to_s}"
8
+ if options[:machine]
9
+ EndState::Graph.new(Object.const_get(options[:machine])).draw.output options[:format] => options[:output]
10
+ else
11
+ puts 'A machine is required'
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ module EndState
4
+ describe Finalizer do
5
+ subject(:finalizer) { Finalizer.new(object, state, params) }
6
+ let(:object) { Struct.new('Machine', :failure_messages, :success_messages, :state).new }
7
+ let(:state) { :a }
8
+ let(:params) { {} }
9
+ before do
10
+ object.failure_messages = []
11
+ object.success_messages = []
12
+ end
13
+
14
+ describe '#add_error' do
15
+ it 'adds an error' do
16
+ finalizer.add_error('error')
17
+ expect(object.failure_messages).to eq ['error']
18
+ end
19
+ end
20
+
21
+ describe '#add_success' do
22
+ it 'adds an success' do
23
+ finalizer.add_error('success')
24
+ expect(object.failure_messages).to eq ['success']
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ module EndState
4
+ describe Guard do
5
+ subject(:guard) { Guard.new(object, state, params) }
6
+ let(:object) { Struct.new('Machine', :failure_messages, :success_messages, :state).new }
7
+ let(:state) { :a }
8
+ let(:params) { {} }
9
+ before do
10
+ object.failure_messages = []
11
+ object.success_messages = []
12
+ end
13
+
14
+ describe '#add_error' do
15
+ it 'adds an error' do
16
+ guard.add_error('error')
17
+ expect(object.failure_messages).to eq ['error']
18
+ end
19
+ end
20
+
21
+ describe '#add_success' do
22
+ it 'adds an success' do
23
+ guard.add_error('success')
24
+ expect(object.failure_messages).to eq ['success']
25
+ end
26
+ end
27
+ end
28
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: end_state
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - alexpeachey
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-05-29 00:00:00.000000000 Z
11
+ date: 2014-05-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -91,13 +91,18 @@ files:
91
91
  - lib/end_state/finalizer.rb
92
92
  - lib/end_state/finalizers.rb
93
93
  - lib/end_state/finalizers/persistence.rb
94
+ - lib/end_state/graph.rb
94
95
  - lib/end_state/guard.rb
96
+ - lib/end_state/messages.rb
95
97
  - lib/end_state/state_machine.rb
96
98
  - lib/end_state/transition.rb
97
99
  - lib/end_state/version.rb
98
100
  - lib/end_state_matchers.rb
101
+ - lib/tasks/end_state.rake
99
102
  - spec/end_state/action_spec.rb
103
+ - spec/end_state/finalizer_spec.rb
100
104
  - spec/end_state/finalizers/persistence_spec.rb
105
+ - spec/end_state/guard_spec.rb
101
106
  - spec/end_state/state_machine_spec.rb
102
107
  - spec/end_state/transition_spec.rb
103
108
  - spec/end_state_spec.rb
@@ -128,7 +133,9 @@ specification_version: 4
128
133
  summary: A State Machine implementation
129
134
  test_files:
130
135
  - spec/end_state/action_spec.rb
136
+ - spec/end_state/finalizer_spec.rb
131
137
  - spec/end_state/finalizers/persistence_spec.rb
138
+ - spec/end_state/guard_spec.rb
132
139
  - spec/end_state/state_machine_spec.rb
133
140
  - spec/end_state/transition_spec.rb
134
141
  - spec/end_state_spec.rb