micromachine 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2009 Michel Martens
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,114 @@
1
+ MicroMachine
2
+ ============
3
+
4
+ Minimal Finite State Machine.
5
+
6
+ Description
7
+ -----------
8
+
9
+ There are many finite state machine implementations for Ruby, and they
10
+ all provide a nice DSL for declaring events, exceptions, callbacks,
11
+ and all kinds of niceties in general.
12
+
13
+ But if all you want is a finite state machine, look no further: this is only
14
+ 22 lines of code and provides everything a finite state machine must have, and
15
+ nothing more.
16
+
17
+ Usage
18
+ -----
19
+
20
+ require 'micromachine'
21
+
22
+ machine = MicroMachine.new(:new) # Initial state.
23
+
24
+ machine.transitions_for[:confirm] = { :new => :confirmed }
25
+ machine.transitions_for[:ignore] = { :new => :ignored }
26
+ machine.transitions_for[:reset] = { :confirmed => :new, :ignored => :new }
27
+
28
+ machine.trigger(:confirm) #=> true
29
+ machine.trigger(:ignore) #=> false
30
+ machine.trigger(:reset) #=> true
31
+ machine.trigger(:ignore) #=> true
32
+
33
+ It can also have callbacks when entering some state:
34
+
35
+ machine.on(:confirmed) do
36
+ puts "Confirmed"
37
+ end
38
+
39
+ Adding MicroMachine to your models
40
+ ----------------------------------
41
+
42
+ The most popular pattern among Ruby libraries that tackle this problem
43
+ is to extend the model and transform it into a finite state machine.
44
+ Instead of working as a mixin, MicroMachine's implementation is by
45
+ composition: you instantiate a finite state machine (or many!) inside
46
+ your model and you are in charge of querying and persisting the state.
47
+ Here's an example of how to use it with an ActiveRecord model:
48
+
49
+ class Event < ActiveRecord::Base
50
+ before_save :persist_confirmation
51
+
52
+ def confirm!
53
+ confirmation.trigger(:confirm)
54
+ end
55
+
56
+ def cancel!
57
+ confirmation.trigger(:cancel)
58
+ end
59
+
60
+ def reset!
61
+ confirmation.trigger(:reset)
62
+ end
63
+
64
+ def confirmation
65
+ @confirmation ||= begin
66
+ @confirmation = MicroMachine.new(confirmation_state || "pending")
67
+ @confirmation.transitions_for[:confirm] = { "pending" => "confirmed" }
68
+ @confirmation.transitions_for[:cancel] = { "confirmed" => "cancelled" }
69
+ @confirmation.transitions_for[:reset] = { "confirmed" => "pending", "cancelled" => "pending" }
70
+ @confirmation
71
+ end
72
+ end
73
+
74
+ private
75
+
76
+ def persist_confirmation
77
+ self.confirmation_state = confirmation.state
78
+ end
79
+ end
80
+
81
+ This example asumes you have a :confirmation_state attribute in your
82
+ model. This may look like a very verbose implementation, but you gain a
83
+ lot in flexibility.
84
+
85
+ Installation
86
+ ------------
87
+
88
+ $ sudo gem install micromachine
89
+
90
+ License
91
+ -------
92
+
93
+ Copyright (c) 2009 Michel Martens for Citrusbyte
94
+
95
+ Permission is hereby granted, free of charge, to any person
96
+ obtaining a copy of this software and associated documentation
97
+ files (the "Software"), to deal in the Software without
98
+ restriction, including without limitation the rights to use,
99
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
100
+ copies of the Software, and to permit persons to whom the
101
+ Software is furnished to do so, subject to the following
102
+ conditions:
103
+
104
+ The above copyright notice and this permission notice shall be
105
+ included in all copies or substantial portions of the Software.
106
+
107
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
108
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
109
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
110
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
111
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
112
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
113
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
114
+ OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,35 @@
1
+ require 'rake'
2
+ require 'rake/gempackagetask'
3
+ require 'rake/testtask'
4
+ require 'rake/clean'
5
+
6
+ gem_spec_file = 'micromachine.gemspec'
7
+
8
+ gem_spec = eval(File.read(gem_spec_file)) rescue nil
9
+
10
+ task :default => :test
11
+
12
+ Rake::TestTask.new(:test) do |t|
13
+ t.pattern = 'test/**/*_test.rb'
14
+ t.verbose = false
15
+ end
16
+
17
+ Rake::GemPackageTask.new(gem_spec) do |pkg|
18
+ pkg.need_zip = false
19
+ pkg.need_tar = false
20
+ rm_f FileList['pkg/**/*.*']
21
+ end if gem_spec
22
+
23
+ desc "Generate the gemspec file."
24
+ task :gemspec do
25
+ require 'erb'
26
+
27
+ File.open(gem_spec_file, 'w') do |f|
28
+ f.write ERB.new(File.read("#{gem_spec_file}.erb")).result(binding)
29
+ end
30
+ end
31
+
32
+ desc "Builds and installs the gem."
33
+ task :install => :repackage do
34
+ `sudo gem install pkg/#{gem_spec.name}-#{gem_spec.version}.gem`
35
+ end
@@ -0,0 +1,24 @@
1
+ require File.join(File.dirname(__FILE__), '../lib/micromachine')
2
+
3
+ fsm = MicroMachine.new(:pending)
4
+ fsm.transitions_for[:confirm] = { :pending => :confirmed }
5
+ fsm.transitions_for[:ignore] = { :pending => :ignored }
6
+ fsm.transitions_for[:reset] = { :confirmed => :pending, :ignored => :pending }
7
+
8
+ puts "Should print Confirmed, Reset and Ignored."
9
+
10
+ if fsm.trigger(:confirm)
11
+ puts "Confirmed"
12
+ end
13
+
14
+ if fsm.trigger(:ignore)
15
+ puts "Ignored"
16
+ end
17
+
18
+ if fsm.trigger(:reset)
19
+ puts "Reset"
20
+ end
21
+
22
+ if fsm.trigger(:ignore)
23
+ puts "Ignored"
24
+ end
@@ -0,0 +1,25 @@
1
+ require 'rubygems'
2
+ require 'micromachine'
3
+
4
+ fsm = MicroMachine.new(:pending)
5
+ fsm.transitions_for[:confirm] = { :pending => :confirmed }
6
+ fsm.transitions_for[:ignore] = { :pending => :ignored }
7
+ fsm.transitions_for[:reset] = { :confirmed => :pending, :ignored => :pending }
8
+
9
+ puts "Should print Confirmed, Reset and Ignored."
10
+
11
+ if fsm.trigger(:confirm)
12
+ puts "Confirmed"
13
+ end
14
+
15
+ if fsm.trigger(:ignore)
16
+ puts "Ignored"
17
+ end
18
+
19
+ if fsm.trigger(:reset)
20
+ puts "Reset"
21
+ end
22
+
23
+ if fsm.trigger(:ignore)
24
+ puts "Ignored"
25
+ end
@@ -0,0 +1,22 @@
1
+ class MicroMachine
2
+ attr :transitions_for
3
+ attr :state
4
+
5
+ def initialize initial_state
6
+ @state = initial_state
7
+ @transitions_for = Hash.new
8
+ @callbacks = Hash.new { |hash, key| hash[key] = [] }
9
+ end
10
+
11
+ def on key, &block
12
+ @callbacks[key] << block
13
+ end
14
+
15
+ def trigger event
16
+ if transitions_for[event][@state]
17
+ @state = transitions_for[event][@state]
18
+ @callbacks[@state].each { |callback| callback.call }
19
+ true
20
+ end
21
+ end
22
+ end
metadata ADDED
@@ -0,0 +1,58 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: micromachine
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.6
5
+ platform: ruby
6
+ authors:
7
+ - Michel Martens
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-03-07 00:00:00 -02:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: michel@soveran.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - lib/micromachine.rb
26
+ - README.markdown
27
+ - LICENSE
28
+ - Rakefile
29
+ - example/micromachine_sample.rb
30
+ - example/micromachine_sample_gem.rb
31
+ has_rdoc: false
32
+ homepage: http://github.com/soveran/micromachine
33
+ post_install_message:
34
+ rdoc_options: []
35
+
36
+ require_paths:
37
+ - lib
38
+ required_ruby_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: "0"
43
+ version:
44
+ required_rubygems_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: "0"
49
+ version:
50
+ requirements: []
51
+
52
+ rubyforge_project:
53
+ rubygems_version: 1.3.1
54
+ signing_key:
55
+ specification_version: 2
56
+ summary: Minimal Finite State Machine.
57
+ test_files: []
58
+