spree-state_machine 2.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/.travis.yml +12 -0
- data/.yardopts +5 -0
- data/CHANGELOG.md +502 -0
- data/Gemfile +3 -0
- data/LICENSE +20 -0
- data/README.md +1246 -0
- data/Rakefile +20 -0
- data/examples/AutoShop_state.png +0 -0
- data/examples/Car_state.png +0 -0
- data/examples/Gemfile +5 -0
- data/examples/Gemfile.lock +14 -0
- data/examples/TrafficLight_state.png +0 -0
- data/examples/Vehicle_state.png +0 -0
- data/examples/auto_shop.rb +13 -0
- data/examples/car.rb +21 -0
- data/examples/doc/AutoShop.html +2856 -0
- data/examples/doc/AutoShop_state.png +0 -0
- data/examples/doc/Car.html +919 -0
- data/examples/doc/Car_state.png +0 -0
- data/examples/doc/TrafficLight.html +2230 -0
- data/examples/doc/TrafficLight_state.png +0 -0
- data/examples/doc/Vehicle.html +7921 -0
- data/examples/doc/Vehicle_state.png +0 -0
- data/examples/doc/_index.html +136 -0
- data/examples/doc/class_list.html +47 -0
- data/examples/doc/css/common.css +1 -0
- data/examples/doc/css/full_list.css +55 -0
- data/examples/doc/css/style.css +322 -0
- data/examples/doc/file_list.html +46 -0
- data/examples/doc/frames.html +13 -0
- data/examples/doc/index.html +136 -0
- data/examples/doc/js/app.js +205 -0
- data/examples/doc/js/full_list.js +173 -0
- data/examples/doc/js/jquery.js +16 -0
- data/examples/doc/method_list.html +734 -0
- data/examples/doc/top-level-namespace.html +105 -0
- data/examples/merb-rest/controller.rb +51 -0
- data/examples/merb-rest/model.rb +28 -0
- data/examples/merb-rest/view_edit.html.erb +24 -0
- data/examples/merb-rest/view_index.html.erb +23 -0
- data/examples/merb-rest/view_new.html.erb +13 -0
- data/examples/merb-rest/view_show.html.erb +17 -0
- data/examples/rails-rest/controller.rb +43 -0
- data/examples/rails-rest/migration.rb +7 -0
- data/examples/rails-rest/model.rb +23 -0
- data/examples/rails-rest/view__form.html.erb +34 -0
- data/examples/rails-rest/view_edit.html.erb +6 -0
- data/examples/rails-rest/view_index.html.erb +25 -0
- data/examples/rails-rest/view_new.html.erb +5 -0
- data/examples/rails-rest/view_show.html.erb +19 -0
- data/examples/traffic_light.rb +9 -0
- data/examples/vehicle.rb +33 -0
- data/lib/state_machine/assertions.rb +36 -0
- data/lib/state_machine/branch.rb +225 -0
- data/lib/state_machine/callback.rb +236 -0
- data/lib/state_machine/core.rb +7 -0
- data/lib/state_machine/core_ext/class/state_machine.rb +5 -0
- data/lib/state_machine/core_ext.rb +2 -0
- data/lib/state_machine/error.rb +13 -0
- data/lib/state_machine/eval_helpers.rb +87 -0
- data/lib/state_machine/event.rb +257 -0
- data/lib/state_machine/event_collection.rb +141 -0
- data/lib/state_machine/extensions.rb +149 -0
- data/lib/state_machine/graph.rb +92 -0
- data/lib/state_machine/helper_module.rb +17 -0
- data/lib/state_machine/initializers/rails.rb +25 -0
- data/lib/state_machine/initializers.rb +4 -0
- data/lib/state_machine/integrations/active_model/locale.rb +11 -0
- data/lib/state_machine/integrations/active_model/observer.rb +33 -0
- data/lib/state_machine/integrations/active_model/observer_update.rb +42 -0
- data/lib/state_machine/integrations/active_model/versions.rb +31 -0
- data/lib/state_machine/integrations/active_model.rb +585 -0
- data/lib/state_machine/integrations/active_record/locale.rb +20 -0
- data/lib/state_machine/integrations/active_record/versions.rb +123 -0
- data/lib/state_machine/integrations/active_record.rb +525 -0
- data/lib/state_machine/integrations/base.rb +100 -0
- data/lib/state_machine/integrations.rb +121 -0
- data/lib/state_machine/machine.rb +2287 -0
- data/lib/state_machine/machine_collection.rb +74 -0
- data/lib/state_machine/macro_methods.rb +522 -0
- data/lib/state_machine/matcher.rb +123 -0
- data/lib/state_machine/matcher_helpers.rb +54 -0
- data/lib/state_machine/node_collection.rb +222 -0
- data/lib/state_machine/path.rb +120 -0
- data/lib/state_machine/path_collection.rb +90 -0
- data/lib/state_machine/state.rb +297 -0
- data/lib/state_machine/state_collection.rb +112 -0
- data/lib/state_machine/state_context.rb +138 -0
- data/lib/state_machine/transition.rb +470 -0
- data/lib/state_machine/transition_collection.rb +245 -0
- data/lib/state_machine/version.rb +3 -0
- data/lib/state_machine/yard/handlers/base.rb +32 -0
- data/lib/state_machine/yard/handlers/event.rb +25 -0
- data/lib/state_machine/yard/handlers/machine.rb +344 -0
- data/lib/state_machine/yard/handlers/state.rb +25 -0
- data/lib/state_machine/yard/handlers/transition.rb +47 -0
- data/lib/state_machine/yard/handlers.rb +12 -0
- data/lib/state_machine/yard/templates/default/class/html/setup.rb +30 -0
- data/lib/state_machine/yard/templates/default/class/html/state_machines.erb +12 -0
- data/lib/state_machine/yard/templates.rb +3 -0
- data/lib/state_machine/yard.rb +8 -0
- data/lib/state_machine.rb +8 -0
- data/lib/yard-state_machine.rb +2 -0
- data/state_machine.gemspec +22 -0
- data/test/files/en.yml +17 -0
- data/test/files/switch.rb +15 -0
- data/test/functional/state_machine_test.rb +1066 -0
- data/test/test_helper.rb +7 -0
- data/test/unit/assertions_test.rb +40 -0
- data/test/unit/branch_test.rb +969 -0
- data/test/unit/callback_test.rb +704 -0
- data/test/unit/error_test.rb +43 -0
- data/test/unit/eval_helpers_test.rb +270 -0
- data/test/unit/event_collection_test.rb +398 -0
- data/test/unit/event_test.rb +1196 -0
- data/test/unit/graph_test.rb +98 -0
- data/test/unit/helper_module_test.rb +17 -0
- data/test/unit/integrations/active_model_test.rb +1245 -0
- data/test/unit/integrations/active_record_test.rb +2551 -0
- data/test/unit/integrations/base_test.rb +104 -0
- data/test/unit/integrations_test.rb +71 -0
- data/test/unit/invalid_event_test.rb +20 -0
- data/test/unit/invalid_parallel_transition_test.rb +18 -0
- data/test/unit/invalid_transition_test.rb +115 -0
- data/test/unit/machine_collection_test.rb +603 -0
- data/test/unit/machine_test.rb +3395 -0
- data/test/unit/matcher_helpers_test.rb +37 -0
- data/test/unit/matcher_test.rb +155 -0
- data/test/unit/node_collection_test.rb +362 -0
- data/test/unit/path_collection_test.rb +266 -0
- data/test/unit/path_test.rb +485 -0
- data/test/unit/state_collection_test.rb +352 -0
- data/test/unit/state_context_test.rb +441 -0
- data/test/unit/state_machine_test.rb +31 -0
- data/test/unit/state_test.rb +1101 -0
- data/test/unit/transition_collection_test.rb +2168 -0
- data/test/unit/transition_test.rb +1558 -0
- metadata +264 -0
@@ -0,0 +1,105 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
3
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
4
|
+
<head>
|
5
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
6
|
+
<title>
|
7
|
+
Top Level Namespace
|
8
|
+
|
9
|
+
— Documentation by YARD 0.7.5
|
10
|
+
|
11
|
+
</title>
|
12
|
+
|
13
|
+
<link rel="stylesheet" href="css/style.css" type="text/css" media="screen" charset="utf-8" />
|
14
|
+
|
15
|
+
<link rel="stylesheet" href="css/common.css" type="text/css" media="screen" charset="utf-8" />
|
16
|
+
|
17
|
+
<script type="text/javascript" charset="utf-8">
|
18
|
+
relpath = '';
|
19
|
+
if (relpath != '') relpath += '/';
|
20
|
+
</script>
|
21
|
+
|
22
|
+
<script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
|
23
|
+
|
24
|
+
<script type="text/javascript" charset="utf-8" src="js/app.js"></script>
|
25
|
+
|
26
|
+
|
27
|
+
</head>
|
28
|
+
<body>
|
29
|
+
<script type="text/javascript" charset="utf-8">
|
30
|
+
if (window.top.frames.main) document.body.className = 'frames';
|
31
|
+
</script>
|
32
|
+
|
33
|
+
<div id="header">
|
34
|
+
<div id="menu">
|
35
|
+
|
36
|
+
<a href="_index.html">Index</a> »
|
37
|
+
|
38
|
+
|
39
|
+
<span class="title">Top Level Namespace</span>
|
40
|
+
|
41
|
+
|
42
|
+
<div class="noframes"><span class="title">(</span><a href="." target="_top">no frames</a><span class="title">)</span></div>
|
43
|
+
</div>
|
44
|
+
|
45
|
+
<div id="search">
|
46
|
+
|
47
|
+
<a id="class_list_link" href="#">Class List</a>
|
48
|
+
|
49
|
+
<a id="method_list_link" href="#">Method List</a>
|
50
|
+
|
51
|
+
<a id="file_list_link" href="#">File List</a>
|
52
|
+
|
53
|
+
</div>
|
54
|
+
<div class="clear"></div>
|
55
|
+
</div>
|
56
|
+
|
57
|
+
<iframe id="search_frame"></iframe>
|
58
|
+
|
59
|
+
<div id="content"><h1>Top Level Namespace
|
60
|
+
|
61
|
+
|
62
|
+
|
63
|
+
</h1>
|
64
|
+
|
65
|
+
<dl class="box">
|
66
|
+
|
67
|
+
|
68
|
+
|
69
|
+
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
|
74
|
+
</dl>
|
75
|
+
<div class="clear"></div>
|
76
|
+
|
77
|
+
<h2>Defined Under Namespace</h2>
|
78
|
+
<p class="children">
|
79
|
+
|
80
|
+
|
81
|
+
|
82
|
+
|
83
|
+
<strong class="classes">Classes:</strong> <span class='object_link'><a href="AutoShop.html" title="AutoShop (class)">AutoShop</a></span>, <span class='object_link'><a href="Car.html" title="Car (class)">Car</a></span>, <span class='object_link'><a href="TrafficLight.html" title="TrafficLight (class)">TrafficLight</a></span>, <span class='object_link'><a href="Vehicle.html" title="Vehicle (class)">Vehicle</a></span>
|
84
|
+
|
85
|
+
|
86
|
+
</p>
|
87
|
+
|
88
|
+
|
89
|
+
|
90
|
+
|
91
|
+
|
92
|
+
|
93
|
+
|
94
|
+
|
95
|
+
|
96
|
+
</div>
|
97
|
+
|
98
|
+
<div id="footer">
|
99
|
+
Generated on Fri Feb 17 08:30:35 2012 by
|
100
|
+
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
101
|
+
0.7.5 (ruby-1.9.2).
|
102
|
+
</div>
|
103
|
+
|
104
|
+
</body>
|
105
|
+
</html>
|
@@ -0,0 +1,51 @@
|
|
1
|
+
class Users < Application
|
2
|
+
# GET /users
|
3
|
+
def index
|
4
|
+
@users = User.all
|
5
|
+
display @users
|
6
|
+
end
|
7
|
+
|
8
|
+
# GET /users/1
|
9
|
+
def show(id)
|
10
|
+
@user = User.get(id)
|
11
|
+
raise NotFound unless @user
|
12
|
+
display @user
|
13
|
+
end
|
14
|
+
|
15
|
+
# GET /users/new
|
16
|
+
def new
|
17
|
+
only_provides :html
|
18
|
+
@user = User.new
|
19
|
+
display @user
|
20
|
+
end
|
21
|
+
|
22
|
+
# GET /users/1/edit
|
23
|
+
def edit(id)
|
24
|
+
only_provides :html
|
25
|
+
@user = User.get(id)
|
26
|
+
raise NotFound unless @user
|
27
|
+
display @user
|
28
|
+
end
|
29
|
+
|
30
|
+
# POST /users
|
31
|
+
def create(user)
|
32
|
+
@user = User.new(user)
|
33
|
+
if @user.save
|
34
|
+
redirect resource(@user), :message => {:notice => "User was successfully created"}
|
35
|
+
else
|
36
|
+
message[:error] = "User failed to be created"
|
37
|
+
render :new
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# PUT /users/1
|
42
|
+
def update(id, user)
|
43
|
+
@user = User.get(id)
|
44
|
+
raise NotFound unless @user
|
45
|
+
if @user.update_attributes(user)
|
46
|
+
redirect resource(@user)
|
47
|
+
else
|
48
|
+
display @user, :edit
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class User
|
2
|
+
include DataMapper::Resource
|
3
|
+
|
4
|
+
property :id, Serial
|
5
|
+
property :name, String
|
6
|
+
|
7
|
+
validates_present :name, :state, :access_state
|
8
|
+
|
9
|
+
state_machine :initial => :unregistered do
|
10
|
+
event :register do
|
11
|
+
transition :unregistered => :registered
|
12
|
+
end
|
13
|
+
|
14
|
+
event :unregister do
|
15
|
+
transition :registered => :unregistered
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
state_machine :access_state, :initial => :enabled do
|
20
|
+
event :enable do
|
21
|
+
transition all => :enabled
|
22
|
+
end
|
23
|
+
|
24
|
+
event :disable do
|
25
|
+
transition all => :disabled
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<h1>Editing User</h1>
|
2
|
+
|
3
|
+
<%= form_for @user, :action => resource(@user) do %>
|
4
|
+
<%= error_messages %>
|
5
|
+
|
6
|
+
<p>
|
7
|
+
<%= text_field :name, :label => 'Name' %>
|
8
|
+
</p>
|
9
|
+
|
10
|
+
<p>
|
11
|
+
<%= label :state %><br />
|
12
|
+
<%= select :state_event, :selected => @user.state_event.to_s, :collection => @user.state_transitions, :value_method => :event, :text_method => :human_to_name, :prompt => @user.human_state_name %>
|
13
|
+
</p>
|
14
|
+
|
15
|
+
<p>
|
16
|
+
<%= label :access_state %><br />
|
17
|
+
<%= select :access_state_event, :selected => @user.access_state_event.to_s, :collection => @user.access_state_transitions, :value_method => :event, :text_method => :human_event, :prompt => "don't change" %>
|
18
|
+
</p>
|
19
|
+
|
20
|
+
<p><%= submit 'Update' %></p>
|
21
|
+
<% end =%>
|
22
|
+
|
23
|
+
<%= link_to 'Show', resource(@user) %> |
|
24
|
+
<%= link_to 'Back', resource(:users) %>
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<h1>Listing Users</h1>
|
2
|
+
|
3
|
+
<table>
|
4
|
+
<tr>
|
5
|
+
<th>Name</th>
|
6
|
+
<th>State</th>
|
7
|
+
<th>Access State</th>
|
8
|
+
</tr>
|
9
|
+
|
10
|
+
<% @users.each do |user| %>
|
11
|
+
<tr>
|
12
|
+
<td><%=h user.name %></td>
|
13
|
+
<td><%=h user.human_state_name %></td>
|
14
|
+
<td><%=h user.human_access_state_name %></td>
|
15
|
+
<td><%= link_to 'Show', resource(user) %></td>
|
16
|
+
<td><%= link_to 'Edit', resource(user, :edit) %></td>
|
17
|
+
</tr>
|
18
|
+
<% end %>
|
19
|
+
</table>
|
20
|
+
|
21
|
+
<br />
|
22
|
+
|
23
|
+
<%= link_to 'New User', resource(:users, :new) %>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<p>
|
2
|
+
<b>Name:</b>
|
3
|
+
<%=h @user.name %>
|
4
|
+
</p>
|
5
|
+
|
6
|
+
<p>
|
7
|
+
<b>State:</b>
|
8
|
+
<%=h @user.human_state_name %>
|
9
|
+
</p>
|
10
|
+
|
11
|
+
<p>
|
12
|
+
<b>Access State:</b>
|
13
|
+
<%=h @user.human_access_state_name %>
|
14
|
+
</p>
|
15
|
+
|
16
|
+
<%= link_to 'Edit', resource(@user, :edit) %> |
|
17
|
+
<%= link_to 'Back', resource(:users) %>
|
@@ -0,0 +1,43 @@
|
|
1
|
+
class UsersController < ApplicationController
|
2
|
+
# GET /users
|
3
|
+
def index
|
4
|
+
@users = User.all
|
5
|
+
end
|
6
|
+
|
7
|
+
# GET /users/1
|
8
|
+
def show
|
9
|
+
@user = User.find(params[:id])
|
10
|
+
end
|
11
|
+
|
12
|
+
# GET /users/new
|
13
|
+
def new
|
14
|
+
@user = User.new
|
15
|
+
end
|
16
|
+
|
17
|
+
# GET /users/1/edit
|
18
|
+
def edit
|
19
|
+
@user = User.find(params[:id])
|
20
|
+
end
|
21
|
+
|
22
|
+
# POST /users
|
23
|
+
def create
|
24
|
+
@user = User.new(params[:user])
|
25
|
+
|
26
|
+
if @user.save
|
27
|
+
redirect_to(@user)
|
28
|
+
else
|
29
|
+
render :action => 'new'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# PUT /users/1
|
34
|
+
def update
|
35
|
+
@user = User.find(params[:id])
|
36
|
+
|
37
|
+
if @user.update_attributes(params[:user])
|
38
|
+
redirect_to(@user)
|
39
|
+
else
|
40
|
+
render :action => 'edit'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class User < ActiveRecord::Base
|
2
|
+
validates_presence_of :name, :state, :access_state
|
3
|
+
|
4
|
+
state_machine :initial => :unregistered do
|
5
|
+
event :register do
|
6
|
+
transition :unregistered => :registered
|
7
|
+
end
|
8
|
+
|
9
|
+
event :unregister do
|
10
|
+
transition :registered => :unregistered
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
state_machine :access_state, :initial => :enabled do
|
15
|
+
event :enable do
|
16
|
+
transition all => :enabled
|
17
|
+
end
|
18
|
+
|
19
|
+
event :disable do
|
20
|
+
transition all => :disabled
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
<%= form_for(@user) do |f| %>
|
2
|
+
<% if @user.errors.any? %>
|
3
|
+
<div id="error_explanation">
|
4
|
+
<h2><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</h2>
|
5
|
+
|
6
|
+
<ul>
|
7
|
+
<% @user.errors.full_messages.each do |msg| %>
|
8
|
+
<li><%= msg %></li>
|
9
|
+
<% end %>
|
10
|
+
</ul>
|
11
|
+
</div>
|
12
|
+
<% end %>
|
13
|
+
|
14
|
+
<div class="field">
|
15
|
+
<%= f.label :name %><br />
|
16
|
+
<%= f.text_field :name %>
|
17
|
+
</div>
|
18
|
+
|
19
|
+
<% unless @user.new_record? %>
|
20
|
+
<div class="field">
|
21
|
+
<%= f.label :state %><br />
|
22
|
+
<%= f.collection_select :state_event, @user.state_transitions, :event, :human_to_name, :include_blank => @user.human_state_name %>
|
23
|
+
</div>
|
24
|
+
|
25
|
+
<div class="field">
|
26
|
+
<%= f.label :access_state %><br />
|
27
|
+
<%= f.collection_select :access_state_event, @user.access_state_transitions, :event, :human_event, :include_blank => "don't change" %>
|
28
|
+
</div>
|
29
|
+
<% end %>
|
30
|
+
|
31
|
+
<div class="actions">
|
32
|
+
<%= f.submit %>
|
33
|
+
</div>
|
34
|
+
<% end %>
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<h1>Listing users</h1>
|
2
|
+
|
3
|
+
<table>
|
4
|
+
<tr>
|
5
|
+
<th>Name</th>
|
6
|
+
<th>State</th>
|
7
|
+
<th>Access State</th>
|
8
|
+
<th></th>
|
9
|
+
<th></th>
|
10
|
+
</tr>
|
11
|
+
|
12
|
+
<% @users.each do |user| %>
|
13
|
+
<tr>
|
14
|
+
<td><%= user.name %></td>
|
15
|
+
<td><%= user.human_state_name %></td>
|
16
|
+
<td><%= user.human_access_state_name %></td>
|
17
|
+
<td><%= link_to 'Show', user %></td>
|
18
|
+
<td><%= link_to 'Edit', edit_user_path(user) %></td>
|
19
|
+
</tr>
|
20
|
+
<% end %>
|
21
|
+
</table>
|
22
|
+
|
23
|
+
<br />
|
24
|
+
|
25
|
+
<%= link_to 'New User', new_user_path %>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<p id="notice"><%= notice %></p>
|
2
|
+
|
3
|
+
<p>
|
4
|
+
<b>Name:</b>
|
5
|
+
<%= @user.name %>
|
6
|
+
</p>
|
7
|
+
|
8
|
+
<p>
|
9
|
+
<b>State:</b>
|
10
|
+
<%= @user.human_state_name %>
|
11
|
+
</p>
|
12
|
+
|
13
|
+
<p>
|
14
|
+
<b>Access State:</b>
|
15
|
+
<%= @user.human_access_state_name %>
|
16
|
+
</p>
|
17
|
+
|
18
|
+
<%= link_to 'Edit', edit_user_path(@user) %> |
|
19
|
+
<%= link_to 'Back', users_path %>
|
data/examples/vehicle.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'state_machine'
|
2
|
+
|
3
|
+
class Vehicle
|
4
|
+
state_machine :initial => :parked do
|
5
|
+
event :park do
|
6
|
+
transition [:idling, :first_gear] => :parked
|
7
|
+
end
|
8
|
+
|
9
|
+
event :ignite do
|
10
|
+
transition :stalled => same, :parked => :idling
|
11
|
+
end
|
12
|
+
|
13
|
+
event :idle do
|
14
|
+
transition :first_gear => :idling
|
15
|
+
end
|
16
|
+
|
17
|
+
event :shift_up do
|
18
|
+
transition :idling => :first_gear, :first_gear => :second_gear, :second_gear => :third_gear
|
19
|
+
end
|
20
|
+
|
21
|
+
event :shift_down do
|
22
|
+
transition :third_gear => :second_gear, :second_gear => :first_gear
|
23
|
+
end
|
24
|
+
|
25
|
+
event :crash do
|
26
|
+
transition [:first_gear, :second_gear, :third_gear] => :stalled
|
27
|
+
end
|
28
|
+
|
29
|
+
event :repair do
|
30
|
+
transition :stalled => :parked
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module StateMachine
|
2
|
+
# Provides a set of helper methods for making assertions about the content
|
3
|
+
# of various objects
|
4
|
+
module Assertions
|
5
|
+
# Validates that the given hash *only* includes the specified valid keys.
|
6
|
+
# If any invalid keys are found, an ArgumentError will be raised.
|
7
|
+
#
|
8
|
+
# == Examples
|
9
|
+
#
|
10
|
+
# options = {:name => 'John Smith', :age => 30}
|
11
|
+
#
|
12
|
+
# assert_valid_keys(options, :name) # => ArgumentError: Invalid key(s): age
|
13
|
+
# assert_valid_keys(options, 'name', 'age') # => ArgumentError: Invalid key(s): age, name
|
14
|
+
# assert_valid_keys(options, :name, :age) # => nil
|
15
|
+
def assert_valid_keys(hash, *valid_keys)
|
16
|
+
invalid_keys = hash.keys - valid_keys
|
17
|
+
raise ArgumentError, "Invalid key(s): #{invalid_keys.join(', ')}" unless invalid_keys.empty?
|
18
|
+
end
|
19
|
+
|
20
|
+
# Validates that the given hash only includes at *most* one of a set of
|
21
|
+
# exclusive keys. If more than one key is found, an ArgumentError will be
|
22
|
+
# raised.
|
23
|
+
#
|
24
|
+
# == Examples
|
25
|
+
#
|
26
|
+
# options = {:only => :on, :except => :off}
|
27
|
+
# assert_exclusive_keys(options, :only) # => nil
|
28
|
+
# assert_exclusive_keys(options, :except) # => nil
|
29
|
+
# assert_exclusive_keys(options, :only, :except) # => ArgumentError: Conflicting keys: only, except
|
30
|
+
# assert_exclusive_keys(options, :only, :except, :with) # => ArgumentError: Conflicting keys: only, except
|
31
|
+
def assert_exclusive_keys(hash, *exclusive_keys)
|
32
|
+
conflicting_keys = exclusive_keys & hash.keys
|
33
|
+
raise ArgumentError, "Conflicting keys: #{conflicting_keys.join(', ')}" unless conflicting_keys.length <= 1
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|