end_state 0.1.0 → 0.2.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 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