simplestate 1.0.3 → 1.0.4

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.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -1
  3. data/README.md +37 -10
  4. data/lib/simplestate/version.rb +1 -1
  5. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 53f1d0883e14a61a86ec02d8359991067a2412b5
4
- data.tar.gz: 38880f1cb1d09b4cacd6b1ea298f2f967f93630a
3
+ metadata.gz: fcc388adfc88a6cd589baa29286bc560d25ccd62
4
+ data.tar.gz: f86c3672aacec20a2634602d52eccd699b72a124
5
5
  SHA512:
6
- metadata.gz: 7499fdb20e9eb419bdb4c60e0a8c4e8397b6d45556190aa42fa3a668c8841173133ad4c9b331fd32202c1098252cfd08b1ad6714f398f04a7fdb6f5571aa34eb
7
- data.tar.gz: 29dcb02a648c3b273c199598eaec5d493f50c831384638eb6c849f77eb882f6546176b36d823b4a37924b4788269f4b007eb49a4dfceacd68aedff0ba9d352ec
6
+ metadata.gz: 7d5546df5a9f232656fdc47950ebd0d120993e43966c5145f4e0130308fce0d4b3fb2e0a066e3588844e02c781de9739df5a27d57730106b5a9702ac601d0183
7
+ data.tar.gz: b0624f028f997363913ebc04b2ee4c88135e8707ea61bf4b1730f55dc9adddf343396e0aa0952de97cf8178c71239307ad0b644ef77be3d195ef53c4e8161d66
data/Gemfile CHANGED
@@ -1,6 +1,7 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'coveralls', require: false
3
+ #gem 'coveralls', require: false
4
+ gem "codeclimate-test-reporter", group: :test, require: nil
4
5
 
5
6
  # Specify your gem's dependencies in simplestate.gemspec
6
7
  gemspec
data/README.md CHANGED
@@ -1,15 +1,39 @@
1
- [![Build Status](https://travis-ci.org/dpneumo/simplestate.svg?branch=master)](https://travis-ci.org/dpneumo/simplestate) [![Coverage Status](https://coveralls.io/repos/github/dpneumo/simplestate/badge.svg?branch=master)](https://coveralls.io/github/dpneumo/simplestate?branch=master)
1
+ [![Gem Version](https://badge.fury.io/rb/simplestate.svg)](https://badge.fury.io/rb/simplestate) [![Build Status](https://travis-ci.org/dpneumo/simplestate.svg?branch=master)](https://travis-ci.org/dpneumo/simplestate)
2
2
  [![Code Climate](https://codeclimate.com/github/dpneumo/simplestate/badges/gpa.svg)](https://codeclimate.com/github/dpneumo/simplestate)
3
3
 
4
4
  # Simplestate
5
+ ````ruby
6
+ class Button < StateHolder
7
+ def initialize(opts={})
8
+ super
9
+ end
10
+ end
5
11
 
6
- Simplestate arose out of a need to build a simple statemachine. This implementation was inspired by Daniel Cadenas' StatePattern gem. (https://github.com/dcadenas/state_pattern)
12
+ class Off < State
13
+ def press; transition_to(On); end
14
+ end
7
15
 
8
- I have chosen to eschew serialization of state for now. SimpleDelegator provides the basic functionality required for this implementation. SimpleDelegator supports dynamically swapping the object to which delegated calls are made.
16
+ class On < State
17
+ def press; transition_to(Off); end
18
+ end
9
19
 
10
- The StateHolder class derives from SimpleDelegator. A 'real' state holding object inherits from StateHolder. StateHolder provides support for transitioning between states. Any method not available on the state holder will be forwarded to the currently held state.
20
+ button = Button.new(start_in: Off)
21
+ button.press # current_state: On
22
+ button.press # current_state: Off
23
+ ````
24
+ # Description
25
+ Simplestate arose out of a desire for a very low ceremony mechanism to implement a state machine. I have used SimpleDelegator (delegate.rb) to implement this. Because SimpleDelegator supports dynamically swapping the object to which methods are delegated, it provides a good base for Simplestate.
26
+
27
+ The StateHolder class provides the required functionality for a basic state machine: methods to set the initial state and to transition to a new state. To complement this a State class is provided to serve as ancestor to the states of the state machine. A State instance stores a reference to the state holder and a __#transition_to__ method which simply calls the state holder's __#transition_to__.
28
+
29
+ StateHolder and State are not expected to be used directly. Rather, they are intended to be inherited from. The child state holder should provide methods not specific to its current state. A child state should provide methods specific to that state. The public methods of a child state act as receivers of event messages via delegation from the state holder. Such events may cause effects that are managed by the current state and may also cause transition to a new state. State change logic is expected to be held within the current state. Two private methods, __#enter__ and __#exit__, *must* be provided by each state. These are called by the state holder __#transition_to__ method at the appropriate points in the state life cycle. Neither __#enter__ nor __#exit__ nor any other private method of a state are intended to be called by a user of the state holder.
30
+
31
+ For convenience StateHolder provides instance methods, __#current_state__ and __#set_new_state__, to provide easy access to the underlying methods, __\_\_getobj\_\___ and __\_\_setobj\_\___, of SimpleDelegator. A method to retrieve the history of state transitions from the state holder, __#state_history__, is also provided. Since the transition history could grow quite large that history is limited to the last 5 transitions by default. The history size limit may be changed via __#hx_size_limit__. That limit may be changed at any time. Changes to the limit will take effect an the next state transition.
32
+
33
+ Simplestate does not provide a DSL for specifying the events, states and allowed state transitions. That logic must be specified within each state. Neither does Simplestate provide any mechanism for serialization. There is no "magic" here. It is just a couple of PORO's. As such, it is very easy to see and to reason about what is happening within Simplestate. It should not be too difficult to add serialization support to Simplestate.
34
+
35
+ As an aside, I have looked into providing the Simplestate functionality via a module. However, I found that the SimpleDelegator class provides delegation via a mechanism that makes a module based Simplestate implementation very difficult to achieve. The complexity of that implementation seemed to be not worth the effort. I think the StatePattern gem by [Daniel Cadenas](https://github.com/dcadenas/state_pattern), the inspiration for Simplestate, ran into just this problem. I chose to avoid that issue by relying solely on inheritance.
11
36
 
12
- The State class from which all 'real' states inherit has private #enter and #exit methods that raise an exception. Real states are expected to override these methods with at least 'no-ops'. Any public methods added to a 'real' state can be called on the object holding the state via inherited SimpleDelegator. #enter and #exit like all private state methods are not reachable via the SimpleDelagator functionality. They are intended for internal use by the state instance.
13
37
 
14
38
  ## Installation
15
39
 
@@ -82,16 +106,16 @@ private
82
106
  end
83
107
  end
84
108
  ```
85
- The subclassed state may provide *private* enter and exit methods. Any other state methods intended to be available via a method call on the state holder must be public. #enter and #exit will always be called appropriately during state transitions.
109
+ The subclassed state must provide *private* __#enter__ and __#exit__ methods. Any other state methods intended to be available via a method call on the state holder must be public. __#enter__ and __#exit__ will always be called appropriately during state transitions.
86
110
 
87
- A state has access to methods on the state holder via #holder:
111
+ A state has access to methods on the state holder via __#holder__:
88
112
 
89
113
  ```ruby
90
114
  holder.a_special_holder_method
91
115
  ```
92
116
 
93
117
  #### version 1.0.0
94
- A state holder tracks the history of state transitions in an array accessed via #state_history. The array size defaults to 5. The last item in the array will be the most recent previous state instance. The size may be set at holder creation in the opts hash (:hx_size_limit). The history size limit has a getter and a setter defined as well. (#hx_size_limit= & #hx_size_limit).
118
+ A state holder tracks the history of state transitions in an array accessed via __#state_history__. The array size defaults to 5. The last item in the array will be the most recent previous state instance. The size may be set at holder creation in the opts hash (:hx_size_limit). The history size limit has a getter and a setter defined as well. (__#hx_size_limit=__ and __#hx_size_limit__).
95
119
 
96
120
  ```ruby
97
121
  class Button < StateHolder
@@ -113,7 +137,7 @@ def test_a_button_returns_its_last_prior_state
113
137
  end
114
138
  ```
115
139
 
116
- Please note that the State instance method, previous_state_class, has been removed in this release.
140
+ Please note that the State instance method, __#previous_state_class__, has been removed in this release.
117
141
 
118
142
  #### version 0.3.0 addition
119
143
  The 0.3.0 version contained a serious code smell: A state was expected to know about the history of state transitions. However, a state should know only the states to which it may transition and it's holder to support triggering those transitions. Knowlege of the transition history belongs with the state holder, if it is tracked at all.
@@ -121,6 +145,10 @@ The 0.3.0 version contained a serious code smell: A state was expected to know a
121
145
  #### usage example
122
146
  The button module (test/dummys/button.rb) provides an example of the usage of Simplestate. Tests of this are provided in simplestate_test.rb.
123
147
 
148
+ ## Alternatives
149
+
150
+ If a DSL is desired, complex state functionality is required, events may arrive asynchronously from multiple sources, or state machine functionality must be provided via inclusion of a module rather than via inheritance then Simplestate is probably not appropriate. Consider looking at the [Statemachine](https://github.com/pluginaweek/state_machine), [AASM](https://github.com/aasm/aasm) or [Workflow](https://github.com/geekq/workflow) gems. [The Ruby Toolbox](https://www.ruby-toolbox.com/categories/state_machines.html) provides links to several other statemachine implementations.
151
+
124
152
  ## Development
125
153
 
126
154
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -135,4 +163,3 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/dpneum
135
163
  ## License
136
164
 
137
165
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
138
-
@@ -1,3 +1,3 @@
1
1
  module Simplestate
2
- VERSION = "1.0.3"
2
+ VERSION = "1.0.4"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simplestate
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mitchell C Kuppinger
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-02-06 00:00:00.000000000 Z
11
+ date: 2016-02-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler