statemachine 1.2.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +12 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +12 -0
- data/Rakefile +21 -20
- data/doc/website/README +6 -0
- data/doc/website/config.yaml +2 -0
- data/doc/website/index.html +39 -0
- data/doc/website/src/default.css +110 -0
- data/doc/website/src/default.template +41 -0
- data/doc/website/src/documentation.page +45 -0
- data/doc/website/src/example.page +13 -0
- data/doc/website/src/example1.page +59 -0
- data/doc/website/src/example2.page +96 -0
- data/doc/website/src/example3.page +76 -0
- data/doc/website/src/example4.page +65 -0
- data/doc/website/src/images/8l_star.png +0 -0
- data/doc/website/src/images/bg.png +0 -0
- data/doc/website/src/images/bottom_border.png +0 -0
- data/doc/website/src/images/bottom_edge.png +0 -0
- data/doc/website/src/images/examples/vending_machine.png +0 -0
- data/doc/website/src/images/examples/vending_machine2.png +0 -0
- data/doc/website/src/images/examples/vending_machine3.png +0 -0
- data/doc/website/src/images/examples/vending_machine4a.png +0 -0
- data/doc/website/src/images/examples/vending_machine4b.png +0 -0
- data/doc/website/src/images/left_edge.png +0 -0
- data/doc/website/src/images/logo.png +0 -0
- data/doc/website/src/images/right_edge.png +0 -0
- data/doc/website/src/images/side_borders.png +0 -0
- data/doc/website/src/index.page +20 -0
- data/generate_tests/dot_graph/turnstile.rb +29 -0
- data/generate_tests/dot_graph/turnstile2.rb +48 -0
- data/generate_tests/java/turnstile.rb +54 -0
- data/generate_tests/java/turnstile2.rb +72 -0
- data/lib/statemachine/action_invokation.rb +0 -19
- data/lib/statemachine/version.rb +2 -2
- data/rails_plugin/README +183 -0
- data/rails_plugin/Rakefile +11 -0
- data/rails_plugin/app/controllers/admin_controller.rb +43 -0
- data/rails_plugin/app/controllers/application.rb +7 -0
- data/rails_plugin/app/controllers/main_controller.rb +34 -0
- data/rails_plugin/app/helpers/admin_helper.rb +2 -0
- data/rails_plugin/app/helpers/application_helper.rb +3 -0
- data/rails_plugin/app/helpers/main_helper.rb +7 -0
- data/rails_plugin/app/models/product.rb +21 -0
- data/rails_plugin/app/models/vending_machine.rb +36 -0
- data/rails_plugin/app/models/vending_machine_interface.rb +101 -0
- data/rails_plugin/app/models/vending_statemachine.rb +41 -0
- data/rails_plugin/app/views/admin/index.rhtml +45 -0
- data/rails_plugin/app/views/layouts/main.rhtml +12 -0
- data/rails_plugin/app/views/main/_info.rhtml +13 -0
- data/rails_plugin/app/views/main/event.rjs +27 -0
- data/rails_plugin/app/views/main/index.rhtml +38 -0
- data/rails_plugin/config/boot.rb +45 -0
- data/rails_plugin/config/database.yml +21 -0
- data/rails_plugin/config/environment.rb +60 -0
- data/rails_plugin/config/environments/development.rb +21 -0
- data/rails_plugin/config/environments/production.rb +18 -0
- data/rails_plugin/config/environments/test.rb +19 -0
- data/rails_plugin/config/routes.rb +23 -0
- data/rails_plugin/db/migrate/001_create_vending_machines.rb +12 -0
- data/rails_plugin/db/migrate/002_create_products.rb +14 -0
- data/rails_plugin/db/migrate/003_add_position_to_products.rb +9 -0
- data/rails_plugin/db/schema.rb +20 -0
- data/rails_plugin/doc/README_FOR_APP +2 -0
- data/rails_plugin/lib/tasks/base.rake +5 -0
- data/rails_plugin/public/.htaccess +40 -0
- data/rails_plugin/public/404.html +30 -0
- data/rails_plugin/public/500.html +30 -0
- data/rails_plugin/public/dispatch.cgi +10 -0
- data/rails_plugin/public/dispatch.fcgi +24 -0
- data/rails_plugin/public/dispatch.rb +10 -0
- data/rails_plugin/public/favicon.ico +0 -0
- data/rails_plugin/public/images/bricks.jpg +0 -0
- data/rails_plugin/public/images/cash_release_button.png +0 -0
- data/rails_plugin/public/images/change.png +0 -0
- data/rails_plugin/public/images/dime.png +0 -0
- data/rails_plugin/public/images/dollar.png +0 -0
- data/rails_plugin/public/images/money_panel.png +0 -0
- data/rails_plugin/public/images/nickel.png +0 -0
- data/rails_plugin/public/images/quarter.png +0 -0
- data/rails_plugin/public/images/rails.png +0 -0
- data/rails_plugin/public/images/vending_machine_body.png +0 -0
- data/rails_plugin/public/index.html +277 -0
- data/rails_plugin/public/javascripts/application.js +2 -0
- data/rails_plugin/public/javascripts/controls.js +833 -0
- data/rails_plugin/public/javascripts/dragdrop.js +942 -0
- data/rails_plugin/public/javascripts/effects.js +1088 -0
- data/rails_plugin/public/javascripts/prototype.js +2515 -0
- data/rails_plugin/public/robots.txt +1 -0
- data/rails_plugin/public/stylesheets/layout.css +163 -0
- data/rails_plugin/script/about +3 -0
- data/rails_plugin/script/breakpointer +3 -0
- data/rails_plugin/script/console +3 -0
- data/rails_plugin/script/destroy +3 -0
- data/rails_plugin/script/generate +3 -0
- data/rails_plugin/script/performance/benchmarker +3 -0
- data/rails_plugin/script/performance/profiler +3 -0
- data/rails_plugin/script/plugin +3 -0
- data/rails_plugin/script/process/inspector +3 -0
- data/rails_plugin/script/process/reaper +3 -0
- data/rails_plugin/script/process/spawner +3 -0
- data/rails_plugin/script/rails_spec +11 -0
- data/rails_plugin/script/rails_spec_server +43 -0
- data/rails_plugin/script/runner +3 -0
- data/rails_plugin/script/server +3 -0
- data/rails_plugin/spec/controllers/admin_controller_spec.rb +7 -0
- data/rails_plugin/spec/controllers/main_controller_spec.rb +38 -0
- data/rails_plugin/spec/fixtures/products.yml +2 -0
- data/rails_plugin/spec/fixtures/vending_machines.yml +2 -0
- data/rails_plugin/spec/helpers/admin_helper_spec.rb +5 -0
- data/rails_plugin/spec/helpers/main_helper_spec.rb +5 -0
- data/rails_plugin/spec/models/product_spec.rb +16 -0
- data/rails_plugin/spec/models/vending_machine_interface_spec.rb +168 -0
- data/rails_plugin/spec/models/vending_machine_spec.rb +30 -0
- data/rails_plugin/spec/models/vending_statemachine_spec.rb +130 -0
- data/rails_plugin/spec/plugins/context_support_spec.rb +28 -0
- data/rails_plugin/spec/plugins/controller_support_spec.rb +98 -0
- data/rails_plugin/spec/spec.opts +1 -0
- data/rails_plugin/spec/spec_helper.rb +28 -0
- data/rails_plugin/spec/views/main/event_spec.rb +61 -0
- data/rails_plugin/vendor/plugins/statemachine/README +4 -0
- data/rails_plugin/vendor/plugins/statemachine/Rakefile +22 -0
- data/rails_plugin/vendor/plugins/statemachine/init.rb +2 -0
- data/rails_plugin/vendor/plugins/statemachine/install.rb +1 -0
- data/rails_plugin/vendor/plugins/statemachine/lib/context_support.rb +22 -0
- data/rails_plugin/vendor/plugins/statemachine/lib/controller_support.rb +85 -0
- data/rails_plugin/vendor/plugins/statemachine/lib/statemachine_on_rails.rb +11 -0
- data/rails_plugin/vendor/plugins/statemachine/tasks/statemachine_tasks.rake +4 -0
- data/spec/action_invokation_spec.rb +1 -1
- data/spec/builder_spec.rb +1 -1
- data/spec/default_transition_spec.rb +1 -1
- data/spec/generate/dot_graph/dot_graph_stagemachine_spec.rb +1 -1
- data/spec/history_spec.rb +1 -1
- data/spec/sm_action_parameterization_spec.rb +1 -1
- data/spec/sm_entry_exit_actions_spec.rb +1 -1
- data/spec/sm_odds_n_ends_spec.rb +1 -1
- data/spec/sm_simple_spec.rb +1 -1
- data/spec/sm_super_state_spec.rb +1 -1
- data/spec/sm_turnstile_spec.rb +1 -1
- data/spec/transition_spec.rb +1 -1
- metadata +162 -46
@@ -0,0 +1,30 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe "VendingMachine class with fixtures loaded" do
|
4
|
+
fixtures :vending_machines, :products
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@vm = VendingMachine.new(:location => "Cafeteria", :cash => 1000)
|
8
|
+
@vm.save!
|
9
|
+
end
|
10
|
+
|
11
|
+
it "Create with location and cash" do
|
12
|
+
loaded = VendingMachine.find(@vm.id)
|
13
|
+
loaded.location.should eql("Cafeteria")
|
14
|
+
loaded.cash.should equal 1000
|
15
|
+
end
|
16
|
+
|
17
|
+
it "Add rack" do
|
18
|
+
@vm.add_product(20, "Water", 150)
|
19
|
+
@vm.save!
|
20
|
+
|
21
|
+
loaded = VendingMachine.find(@vm.id)
|
22
|
+
loaded.products.length.should equal 1
|
23
|
+
loaded.products[0].name.should eql("Water")
|
24
|
+
loaded.products[0].price.should eql(150)
|
25
|
+
loaded.products[0].inventory.should equal 20
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe "Vending Statemachine" do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@sm = VendingStatemachine.statemachine
|
7
|
+
@context = mock("context")
|
8
|
+
@sm.context = @context
|
9
|
+
end
|
10
|
+
|
11
|
+
it "start state" do
|
12
|
+
@sm.state.should equal :standby
|
13
|
+
end
|
14
|
+
|
15
|
+
it "dollar" do
|
16
|
+
check_money_event(:dollar, :add_dollar)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "quarter" do
|
20
|
+
check_money_event(:quarter, :add_quarter)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "dime" do
|
24
|
+
check_money_event(:dime, :add_dime)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "nickel" do
|
28
|
+
check_money_event(:nickel, :add_nickel)
|
29
|
+
end
|
30
|
+
|
31
|
+
def check_money_event(event, method)
|
32
|
+
@context.should_receive(:clear_dispensers)
|
33
|
+
@context.should_receive(method)
|
34
|
+
@context.should_receive(:check_max_price)
|
35
|
+
|
36
|
+
@sm.process_event(event)
|
37
|
+
@sm.state.should equal :collecting_money
|
38
|
+
end
|
39
|
+
|
40
|
+
it "standby selection" do
|
41
|
+
@context.should_receive(:clear_dispensers)
|
42
|
+
|
43
|
+
@sm.selection
|
44
|
+
@sm.state.should equal :standby
|
45
|
+
end
|
46
|
+
|
47
|
+
it "standby collecting_money" do
|
48
|
+
@sm.state = :collecting_money
|
49
|
+
@context.should_receive(:load_product).with(123)
|
50
|
+
@context.should_receive(:check_affordability)
|
51
|
+
|
52
|
+
@sm.selection(123)
|
53
|
+
@sm.state.should equal :validating_purchase
|
54
|
+
end
|
55
|
+
|
56
|
+
it "reached max_price" do
|
57
|
+
@sm.state = :collecting_money
|
58
|
+
@context.should_receive(:refuse_money)
|
59
|
+
|
60
|
+
@sm.reached_max_price
|
61
|
+
@sm.state.should equal :max_price_tendered
|
62
|
+
end
|
63
|
+
|
64
|
+
it "accept purchase" do
|
65
|
+
@sm.state = :validating_purchase
|
66
|
+
@context.should_receive(:make_sale)
|
67
|
+
|
68
|
+
@sm.accept_purchase
|
69
|
+
@sm.state.should equal :standby
|
70
|
+
end
|
71
|
+
|
72
|
+
it "refuse purchase" do
|
73
|
+
@sm.state = :validating_purchase
|
74
|
+
@context.should_receive(:check_max_price)
|
75
|
+
|
76
|
+
@sm.refuse_purchase
|
77
|
+
@sm.state.should equal :collecting_money
|
78
|
+
end
|
79
|
+
|
80
|
+
it "money in max_price_tendered" do
|
81
|
+
@sm.state = :max_price_tendered
|
82
|
+
|
83
|
+
@sm.dollar
|
84
|
+
@sm.state.should equal :max_price_tendered
|
85
|
+
@sm.quarter
|
86
|
+
@sm.state.should equal :max_price_tendered
|
87
|
+
@sm.dime
|
88
|
+
@sm.state.should equal :max_price_tendered
|
89
|
+
@sm.nickel
|
90
|
+
@sm.state.should equal :max_price_tendered
|
91
|
+
end
|
92
|
+
|
93
|
+
it "selection in max_price_tendered" do
|
94
|
+
@sm.state = :max_price_tendered
|
95
|
+
@context.should_receive(:load_and_make_sale).with(123)
|
96
|
+
@context.should_receive(:accept_money)
|
97
|
+
|
98
|
+
@sm.selection(123)
|
99
|
+
@sm.state.should equal :standby
|
100
|
+
end
|
101
|
+
|
102
|
+
it "release money from standby" do
|
103
|
+
@context.should_receive(:clear_dispensers)
|
104
|
+
@sm.release_money
|
105
|
+
|
106
|
+
@sm.state.should equal :standby
|
107
|
+
end
|
108
|
+
|
109
|
+
it "release money from collecting money" do
|
110
|
+
@sm.state = :collecting_money
|
111
|
+
@context.should_receive(:dispense_change)
|
112
|
+
|
113
|
+
@sm.release_money
|
114
|
+
|
115
|
+
@sm.state.should equal :standby
|
116
|
+
end
|
117
|
+
|
118
|
+
it "release money from max_price_tendered" do
|
119
|
+
@sm.state = :max_price_tendered
|
120
|
+
@context.should_receive(:dispense_change)
|
121
|
+
@context.should_receive(:accept_money)
|
122
|
+
|
123
|
+
@sm.release_money
|
124
|
+
|
125
|
+
@sm.state.should equal :standby
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
|
130
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe "Context Support" do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@product = Product.new(:name => "Chicken")
|
7
|
+
@product.save!
|
8
|
+
end
|
9
|
+
|
10
|
+
it "Active Recrods Marshalled Compact" do
|
11
|
+
io = StringIO.new("")
|
12
|
+
Marshal.dump(@product, io)
|
13
|
+
io.rewind
|
14
|
+
|
15
|
+
dump = io.read
|
16
|
+
dump.should_not include("Chicken")
|
17
|
+
end
|
18
|
+
|
19
|
+
it "Active Records Loaded properly" do
|
20
|
+
io = StringIO.new("")
|
21
|
+
Marshal.dump(@product, io)
|
22
|
+
io.rewind
|
23
|
+
|
24
|
+
loaded = Marshal.load(io)
|
25
|
+
loaded.name.should eql("Chicken")
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
class SampleContext
|
4
|
+
include Statemachine::ContextSupport
|
5
|
+
end
|
6
|
+
|
7
|
+
class SampleStatemachine
|
8
|
+
attr_accessor :context
|
9
|
+
end
|
10
|
+
|
11
|
+
class SampleController
|
12
|
+
|
13
|
+
include Statemachine::ControllerSupport
|
14
|
+
supported_by_statemachine SampleContext, lambda { SampleStatemachine.new }
|
15
|
+
|
16
|
+
attr_accessor :session, :initialized, :before, :after, :params, :can_continue
|
17
|
+
|
18
|
+
def initialize(statemachine, context)
|
19
|
+
@statemachine = statemachine
|
20
|
+
@context = context
|
21
|
+
@session = {}
|
22
|
+
@can_continue = true
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize_context(*args)
|
26
|
+
@initialized = true
|
27
|
+
end
|
28
|
+
|
29
|
+
def before_event
|
30
|
+
@before = true
|
31
|
+
return @can_continue
|
32
|
+
end
|
33
|
+
|
34
|
+
def after_event
|
35
|
+
@after = true
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "State Machine Support" do
|
41
|
+
|
42
|
+
before(:each) do
|
43
|
+
@statemachine = mock("statemachine")
|
44
|
+
@context = mock("context")
|
45
|
+
@controller = SampleController.new(@statemachine, @context)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "save state" do
|
49
|
+
@controller.send(:save_state)
|
50
|
+
|
51
|
+
@controller.session[:samplecontroller_state].should equal @context
|
52
|
+
end
|
53
|
+
|
54
|
+
it "recall state" do
|
55
|
+
@controller.session[:samplecontroller_state] = @context
|
56
|
+
@context.should_receive(:statemachine)
|
57
|
+
|
58
|
+
@controller.send(:recall_state)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "new context" do
|
62
|
+
@controller = SampleController.new(nil, nil)
|
63
|
+
@controller.send(:new_context)
|
64
|
+
|
65
|
+
@controller.context.should_not equal nil
|
66
|
+
@controller.statemachine.should_not equal nil
|
67
|
+
@controller.context.statemachine.should equal @controller.statemachine
|
68
|
+
@controller.statemachine.context.should equal @controller.context
|
69
|
+
@controller.initialized.should equal true
|
70
|
+
end
|
71
|
+
|
72
|
+
it "event action" do
|
73
|
+
@controller.params = {:event => "boo"}
|
74
|
+
@controller.session[:samplecontroller_state] = @context
|
75
|
+
@context.should_receive(:statemachine).and_return(@statemachine)
|
76
|
+
@statemachine.should_receive(:process_event).with("boo", nil)
|
77
|
+
|
78
|
+
@controller.event
|
79
|
+
|
80
|
+
@controller.before.should equal true
|
81
|
+
@controller.after.should equal true
|
82
|
+
end
|
83
|
+
|
84
|
+
it "the event is not invoked is before_event return false" do
|
85
|
+
@controller.params = {:event => "boo"}
|
86
|
+
@controller.session[:samplecontroller_state] = @context
|
87
|
+
@context.should_not_receive(:statemachine)
|
88
|
+
@statemachine.should_not_receive(:process_event)
|
89
|
+
@controller.can_continue = false
|
90
|
+
|
91
|
+
@controller.event
|
92
|
+
|
93
|
+
@controller.before.should equal true
|
94
|
+
@controller.after.should_not equal true
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# This file is copied to ~/spec when you run 'ruby script/generate rspec'
|
2
|
+
# from the project root directory.
|
3
|
+
ENV["RAILS_ENV"] ||= "test"
|
4
|
+
require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
|
5
|
+
require 'spec/rails'
|
6
|
+
|
7
|
+
require 'statemachine_on_rails'
|
8
|
+
|
9
|
+
# Even if you're using RSpec, RSpec on Rails is reusing some of the
|
10
|
+
# Rails-specific extensions for fixtures and stubbed requests, response
|
11
|
+
# and other things (via RSpec's inherit mechanism). These extensions are
|
12
|
+
# tightly coupled to Test::Unit in Rails, which is why you're seeing it here.
|
13
|
+
module Spec
|
14
|
+
module Rails
|
15
|
+
module Runner
|
16
|
+
class EvalContext < Test::Unit::TestCase
|
17
|
+
self.use_transactional_fixtures = true
|
18
|
+
self.use_instantiated_fixtures = false
|
19
|
+
self.fixture_path = RAILS_ROOT + '/spec/fixtures'
|
20
|
+
|
21
|
+
# You can set up your global fixtures here, or you
|
22
|
+
# can do it in individual contexts using "fixtures :table_a, table_b".
|
23
|
+
#
|
24
|
+
#self.global_fixtures = :table_a, :table_b
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
|
3
|
+
class Stub
|
4
|
+
attr_reader :id
|
5
|
+
|
6
|
+
def initialize(id)
|
7
|
+
@id = id
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "Event View" do
|
12
|
+
|
13
|
+
before(:each) do
|
14
|
+
@display = mock("display")
|
15
|
+
@display.stub!(:message).and_return("$123.45")
|
16
|
+
@display.stub!(:affordable_items).and_return([Stub.new(1)])
|
17
|
+
@display.stub!(:non_affordable_items).and_return([Stub.new(2)])
|
18
|
+
@display.stub!(:sold_out_items).and_return([Stub.new(3)])
|
19
|
+
@display.stub!(:dispensed_item).and_return(Product.new(:name => "Milk"))
|
20
|
+
@display.stub!(:change).and_return("$0.25")
|
21
|
+
|
22
|
+
@vending_machine = mock("vending machine")
|
23
|
+
@vending_machine.stub!(:location).and_return("Downstairs")
|
24
|
+
@vending_machine.stub!(:cash_str).and_return("$10.00")
|
25
|
+
@vending_machine.stub!(:products).and_return([])
|
26
|
+
|
27
|
+
assigns[:context] = @display
|
28
|
+
assigns[:vending_machine] = @vending_machine
|
29
|
+
|
30
|
+
render "/main/event"
|
31
|
+
end
|
32
|
+
|
33
|
+
it "message" do
|
34
|
+
response.should have_rjs(:replace_html, "quartz_screen", ")$123.45"
|
35
|
+
end
|
36
|
+
|
37
|
+
it "affordable items" do
|
38
|
+
response.body.should include("document.getElementById('product_1').className)= 'affordable'"
|
39
|
+
end
|
40
|
+
|
41
|
+
it "non affordable items" do
|
42
|
+
response.body.should include("document.getElementById('product_2').className)= 'non_affordable'"
|
43
|
+
end
|
44
|
+
|
45
|
+
it "sold_out" do
|
46
|
+
response.should have_rjs(:replace_html, "product_3_price", ")<span style=\"color: red;\">SOLD OUT</span>"
|
47
|
+
end
|
48
|
+
|
49
|
+
it "dispenser" do
|
50
|
+
response.should have_rjs(:replace_html, "dispenser", ")<p>Milk</p>"
|
51
|
+
response.should have_rjs(:show, "dispenser")
|
52
|
+
end
|
53
|
+
|
54
|
+
it "change" do
|
55
|
+
response.should have_rjs(:replace_html, "change_amount", ")<p>$0.25</p>"
|
56
|
+
response.should have_rjs(:show, "change_amount")
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
|
61
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
desc 'Default: run unit tests.'
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
desc 'Test the statemachine_controller plugin.'
|
9
|
+
Rake::TestTask.new(:test) do |t|
|
10
|
+
t.libs << 'lib'
|
11
|
+
t.pattern = 'test/**/*_test.rb'
|
12
|
+
t.verbose = true
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'Generate documentation for the statemachine_controller plugin.'
|
16
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
17
|
+
rdoc.rdoc_dir = 'rdoc'
|
18
|
+
rdoc.title = 'StatemachineController'
|
19
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
20
|
+
rdoc.rdoc_files.include('README')
|
21
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
22
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
# Install hook code here
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Statemachine
|
2
|
+
|
3
|
+
module ContextSupport
|
4
|
+
|
5
|
+
attr_accessor :statemachine, :context
|
6
|
+
|
7
|
+
end
|
8
|
+
|
9
|
+
module ActiveRecordMarshalling
|
10
|
+
def marshal_dump
|
11
|
+
return self.id
|
12
|
+
end
|
13
|
+
|
14
|
+
def marshal_load(id)
|
15
|
+
@attributes = {}
|
16
|
+
@new_record = false
|
17
|
+
self.id = id
|
18
|
+
self.reload
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'statemachine'
|
2
|
+
|
3
|
+
module Statemachine
|
4
|
+
module ControllerSupport
|
5
|
+
|
6
|
+
def self.included(base)
|
7
|
+
base.extend SupportMacro
|
8
|
+
end
|
9
|
+
|
10
|
+
module SupportMacro
|
11
|
+
|
12
|
+
def supported_by_statemachine(a_context_class, a_statemachine_creation)
|
13
|
+
self.extend ClassMethods
|
14
|
+
self.send(:include, InstanceMethods)
|
15
|
+
|
16
|
+
self.context_class = a_context_class
|
17
|
+
self.statemachine_creation = a_statemachine_creation
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
module ClassMethods
|
23
|
+
|
24
|
+
attr_accessor :context_class, :statemachine_creation
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
module InstanceMethods
|
29
|
+
|
30
|
+
attr_reader :statemachine, :context
|
31
|
+
|
32
|
+
def event
|
33
|
+
can_continue = before_event
|
34
|
+
if can_continue
|
35
|
+
recall_state
|
36
|
+
puts "@context_event1: #{@context}"
|
37
|
+
event = params[:event]
|
38
|
+
arg = params[:arg]
|
39
|
+
@statemachine.process_event(event, arg)
|
40
|
+
after_event
|
41
|
+
save_state
|
42
|
+
puts "@context_event2: #{@context}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
protected
|
47
|
+
|
48
|
+
def before_event
|
49
|
+
return true
|
50
|
+
end
|
51
|
+
|
52
|
+
def after_event
|
53
|
+
end
|
54
|
+
|
55
|
+
def new_context(*args)
|
56
|
+
@context = self.class.context_class.new
|
57
|
+
puts "@context_new_context: #{@context}"
|
58
|
+
@statemachine = self.class.statemachine_creation.call(*args)
|
59
|
+
@statemachine.context = @context
|
60
|
+
@context.statemachine = @statemachine
|
61
|
+
initialize_context(*args)
|
62
|
+
save_state
|
63
|
+
end
|
64
|
+
|
65
|
+
def save_state
|
66
|
+
session[state_session_key] = @context
|
67
|
+
end
|
68
|
+
|
69
|
+
def initialize_context(*args)
|
70
|
+
end
|
71
|
+
|
72
|
+
def prepare_for_render
|
73
|
+
end
|
74
|
+
|
75
|
+
def recall_state
|
76
|
+
@context = session[state_session_key]
|
77
|
+
@statemachine = @context.statemachine
|
78
|
+
end
|
79
|
+
|
80
|
+
def state_session_key
|
81
|
+
return "#{self.class.name.downcase}_state".to_sym
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|