soveran-micromachine 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +48 -3
- data/Rakefile +0 -27
- data/lib/micromachine.rb +0 -20
- data/micromachine.gemspec +14 -0
- metadata +2 -1
data/README.markdown
CHANGED
@@ -11,7 +11,7 @@ all provide a nice DSL for declaring events, exceptions, callbacks,
|
|
11
11
|
and all kinds of niceties in general.
|
12
12
|
|
13
13
|
But if all you want is a finite state machine, look no further: this is only
|
14
|
-
|
14
|
+
22 lines of code and provides everything a finite state machine must have, and
|
15
15
|
nothing more.
|
16
16
|
|
17
17
|
Usage
|
@@ -36,11 +36,56 @@ It can also have callbacks when entering some state:
|
|
36
36
|
puts "Confirmed"
|
37
37
|
end
|
38
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
|
+
|
39
85
|
Installation
|
40
86
|
------------
|
41
87
|
|
42
|
-
$ gem
|
43
|
-
$ sudo gem install soveran-micromachine
|
88
|
+
$ sudo gem install micromachine
|
44
89
|
|
45
90
|
License
|
46
91
|
-------
|
data/Rakefile
CHANGED
@@ -1,11 +1,4 @@
|
|
1
|
-
require 'rake'
|
2
|
-
require 'rake/gempackagetask'
|
3
1
|
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
2
|
|
10
3
|
task :default => :test
|
11
4
|
|
@@ -13,23 +6,3 @@ Rake::TestTask.new(:test) do |t|
|
|
13
6
|
t.pattern = 'test/**/*_test.rb'
|
14
7
|
t.verbose = false
|
15
8
|
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
|
data/lib/micromachine.rb
CHANGED
@@ -1,23 +1,3 @@
|
|
1
|
-
# Finite State Machine
|
2
|
-
#
|
3
|
-
# Usage:
|
4
|
-
#
|
5
|
-
# machine = MicroMachine.new(:new) # Initial state.
|
6
|
-
#
|
7
|
-
# machine.transitions_for[:confirm] = { :new => :confirmed }
|
8
|
-
# machine.transitions_for[:ignore] = { :new => :ignored }
|
9
|
-
# machine.transitions_for[:reset] = { :confirmed => :new, :ignored => :new }
|
10
|
-
#
|
11
|
-
# machine.trigger(:confirm) #=> true
|
12
|
-
# machine.trigger(:ignore) #=> false
|
13
|
-
# machine.trigger(:reset) #=> true
|
14
|
-
# machine.trigger(:ignore) #=> true
|
15
|
-
#
|
16
|
-
# It also handles callbacks that are executed when entering a different state.
|
17
|
-
#
|
18
|
-
# machine.on(:confirmed) do
|
19
|
-
# puts "Confirmed"
|
20
|
-
# end
|
21
1
|
class MicroMachine
|
22
2
|
attr :transitions_for
|
23
3
|
attr :state
|
@@ -0,0 +1,14 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'micromachine'
|
3
|
+
s.version = '0.0.7'
|
4
|
+
s.summary = %{Minimal Finite State Machine.}
|
5
|
+
s.date = %q{2009-03-07}
|
6
|
+
s.author = "Michel Martens"
|
7
|
+
s.email = "michel@soveran.com"
|
8
|
+
s.homepage = "http://github.com/soveran/micromachine"
|
9
|
+
s.files = ["lib/micromachine.rb", "README.markdown", "LICENSE", "Rakefile", "micromachine.gemspec", "example/micromachine_sample.rb", "example/micromachine_sample_gem.rb"]
|
10
|
+
s.require_paths = ['lib']
|
11
|
+
s.has_rdoc = false
|
12
|
+
s.specification_version = 2 if s.respond_to? :specification_version=
|
13
|
+
end
|
14
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: soveran-micromachine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michel Martens
|
@@ -26,6 +26,7 @@ files:
|
|
26
26
|
- README.markdown
|
27
27
|
- LICENSE
|
28
28
|
- Rakefile
|
29
|
+
- micromachine.gemspec
|
29
30
|
- example/micromachine_sample.rb
|
30
31
|
- example/micromachine_sample_gem.rb
|
31
32
|
has_rdoc: false
|