state_shifter 0.7.1 → 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -6,6 +6,7 @@ source "http://rubygems.org"
6
6
  # Add dependencies to develop your gem here.
7
7
  # Include everything needed to run rake, tests, features, etc.
8
8
  group :development do
9
+ gem 'activerecord', '~> 3.2.x'
9
10
  gem "rspec", "~> 2.8.0"
10
11
  gem "yard", "~> 0.7"
11
12
  gem 'redcarpet'
data/Gemfile.lock CHANGED
@@ -1,8 +1,22 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
+ activemodel (3.2.8)
5
+ activesupport (= 3.2.8)
6
+ builder (~> 3.0.0)
7
+ activerecord (3.2.8)
8
+ activemodel (= 3.2.8)
9
+ activesupport (= 3.2.8)
10
+ arel (~> 3.0.2)
11
+ tzinfo (~> 0.3.29)
12
+ activesupport (3.2.8)
13
+ i18n (~> 0.6)
14
+ multi_json (~> 1.0)
15
+ arel (3.0.2)
16
+ builder (3.0.0)
4
17
  diff-lcs (1.1.3)
5
18
  git (1.2.5)
19
+ i18n (0.6.0)
6
20
  jeweler (1.8.4)
7
21
  bundler (~> 1.0)
8
22
  git (>= 1.2.5)
@@ -26,12 +40,14 @@ GEM
26
40
  multi_json (~> 1.0)
27
41
  simplecov-html (~> 0.5.3)
28
42
  simplecov-html (0.5.3)
43
+ tzinfo (0.3.33)
29
44
  yard (0.8.2.1)
30
45
 
31
46
  PLATFORMS
32
47
  ruby
33
48
 
34
49
  DEPENDENCIES
50
+ activerecord (~> 3.2.x)
35
51
  bundler (~> 1.1.0)
36
52
  jeweler (~> 1.8.4)
37
53
  rdoc (~> 3.12)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.7.1
1
+ 0.7.2
@@ -0,0 +1,97 @@
1
+ class Advanced
2
+ include StateShifter::Definition
3
+
4
+ ###
5
+
6
+ state_machine do
7
+
8
+ state :initialized do
9
+
10
+ event :start_date_changed, :call => :handle_start_date_changed
11
+ event :forced_start => :running
12
+ event :start_date_reached => :running, :if => :start_date_reached?
13
+ event :abort_initialized_contest => :finalized
14
+ end
15
+
16
+ state :running do
17
+
18
+ on_entry do |previous_state, trigger_event|
19
+ running_entry previous_state, trigger_event
20
+ end
21
+
22
+ event :abort_running_contest => :notify_stakeholders
23
+ event :changed_properties
24
+ event :keep_users_engaged
25
+ event :deadline_reached => :notify_organizers, :if => :entries_deadline_reached?
26
+ event :spots_filled => :notify_organizers, :if => :spots_filled?
27
+ event :deadline_reached_without_approvals => :notify_pending_users, :if => :entries_deadline_reached_without_approvals?
28
+ event :deadline_reached_without_entries => :finalized, :if => :entries_deadline_reached_without_entries?
29
+ end
30
+
31
+ state :notify_organizers do
32
+ on_entry :send_notification_to_organizers
33
+ event :organizers_notified => :awaiting_organizer_reply
34
+ end
35
+
36
+ state :awaiting_organizer_reply do
37
+ event :organizer_confirmation_missing => :notify_stakeholders, :if => :organizer_confirmation_deadline_reached?
38
+ event :keep_organizers_engaged
39
+ event :organizer_confirmation_received => :notify_approved_users
40
+ event :organizer_has_more_tickets => :running
41
+ end
42
+
43
+ state :notify_stakeholders do
44
+ on_entry :send_notification_to_stakeholders
45
+ event :stakeholders_notified => :cancelled
46
+ end
47
+
48
+ state :cancelled
49
+
50
+ state :notify_pending_users do
51
+ on_entry :send_notification_to_pending_users
52
+ event :pending_users_notified => :finalized
53
+ end
54
+
55
+ state :notify_approved_users do
56
+ on_entry :send_notification_to_approved_users
57
+ event :approved_users_notified => :send_list_to_organizers
58
+ end
59
+
60
+ state :send_list_to_organizers do
61
+ on_entry :send_guestlist_to_organizers
62
+ event :list_sent_to_organizers => :awaiting_attendance
63
+ end
64
+
65
+ state :awaiting_attendance do
66
+ event :remind_to_fill_in_report => :create_report_filling_requests
67
+ end
68
+
69
+ state :create_report_filling_requests do
70
+ on_entry :send_report_filling_requests
71
+ event :finalize => :finalized
72
+ end
73
+
74
+ state :finalized
75
+
76
+ on_transition do |from,to,trigger_event, duration|
77
+ benchmark from, to, trigger_event, duration
78
+ end
79
+ end
80
+
81
+ persist_attribute :lollies
82
+
83
+ ###
84
+
85
+ def entries_deadline_reached?
86
+ true
87
+ end
88
+
89
+ def running_entry previous_state, trigger_event
90
+ #
91
+ end
92
+
93
+ def benchmark from, to, trigger_event, duration
94
+ #
95
+ end
96
+
97
+ end
@@ -2,9 +2,15 @@ module StateShifter
2
2
  module Definition
3
3
  module ClassMethods
4
4
 
5
- attr_accessor :state_machine_definition
5
+ attr_accessor :state_machine_definition, :persist_attr_name
6
+
7
+ def persist_attribute attr_name
8
+ raise ::StateShifter::PersistenceAttributeAlreadyDefined if @persist_attr_name
9
+ @persist_attr_name = attr_name.to_sym
10
+ end
6
11
 
7
12
  def state_machine &definition
13
+ @persist_attr_name ||= :current_state
8
14
  @state_machine_definition = Contents.new(&definition)
9
15
 
10
16
  @state_machine_definition.states.each do |state_name, state_definition|
@@ -18,7 +24,7 @@ module StateShifter
18
24
 
19
25
  state_machine_definition.get(:state, from_state).events.each do |event_name, event_def|
20
26
  if event_def.has_guards? && check_guards
21
- next if @subject.send(:check_guards, event_name).is_a?(Array)
27
+ next if self.send(:check_guards, event_name).is_a?(Array)
22
28
  end
23
29
 
24
30
  next_states_hash.merge!( event_def.to.nil? ? { from_state.to_sym => event_name } : { event_def.to => event_def.name } )
@@ -1,7 +1,5 @@
1
1
  module StateShifter
2
-
3
2
  module Definition
4
-
5
3
  class Contents
6
4
 
7
5
  attr_accessor :states, :initial_state, :events, :on_transition_proc
@@ -61,6 +59,12 @@ module StateShifter
61
59
  end
62
60
  end
63
61
 
62
+ def on_transition &proc_contents
63
+ @on_transition_proc = proc_contents
64
+ end
65
+
66
+ ### end of DSL methods
67
+
64
68
  def get key, what
65
69
  case key
66
70
  when :event
@@ -70,16 +74,10 @@ module StateShifter
70
74
  end
71
75
  end
72
76
 
73
- def on_transition &proc_contents
74
- @on_transition_proc = proc_contents
75
- end
76
-
77
77
  def has_on_transition_proc?
78
78
  !@on_transition_proc.nil?
79
79
  end
80
80
 
81
81
  end
82
-
83
82
  end
84
-
85
83
  end
@@ -1,14 +1,17 @@
1
1
  module StateShifter
2
-
3
2
  module Definition
4
-
5
3
  module InstanceMethods
6
4
 
7
- attr_accessor :current_state, :state_machine_definition
5
+ def current_state
6
+ @current_state ||= get_current_state
7
+ end
8
8
 
9
- def initialize
10
- @current_state = state_machine_definition.initial_state.name.to_sym
11
- @subject = self
9
+ def get_current_state
10
+ instance_variable_defined?(:@current_state) ? @current_state : state_machine_definition.initial_state.name.to_sym
11
+ end
12
+
13
+ def set_current_state value
14
+ @current_state = value
12
15
  end
13
16
 
14
17
  def state_machine_definition
@@ -42,14 +45,14 @@ module StateShifter
42
45
  def check_event_callbacks event_name
43
46
  event_def = state_machine_definition.get(:event, event_name)
44
47
  begin
45
- @subject.send event_def.callback
48
+ self.send event_def.callback
46
49
  rescue NoMethodError
47
50
  raise ::StateShifter::CallbackMethodNotDefined, event_def.callback
48
51
  end
49
52
  end
50
53
 
51
54
  def current_state_def
52
- state_machine_definition.get(:state, @current_state)
55
+ state_machine_definition.get(:state, current_state)
53
56
  end
54
57
 
55
58
  def call_state_entry_callback trigger, old_state
@@ -57,12 +60,12 @@ module StateShifter
57
60
 
58
61
  if proc_or_method_name.is_a?(Symbol)
59
62
  begin
60
- @subject.send proc_or_method_name
63
+ self.send proc_or_method_name
61
64
  rescue NoMethodError
62
65
  raise ::StateShifter::CallbackMethodNotDefined, proc_or_method_name
63
66
  end
64
67
  else
65
- @subject.instance_exec(old_state, trigger.to_sym, &proc_or_method_name)
68
+ self.instance_exec(old_state, trigger.to_sym, &proc_or_method_name)
66
69
  end
67
70
  end
68
71
 
@@ -70,15 +73,16 @@ module StateShifter
70
73
  _start = Time.now
71
74
 
72
75
  # BOOP!
73
- old_state = @current_state
74
- @current_state = args[:to].to_sym
76
+ old_state = current_state
77
+ set_current_state args[:to].to_sym
75
78
  #
76
79
 
77
80
  check_event_callbacks(args[:trigger]) if state_machine_definition.get(:event, args[:trigger]).has_callback?
78
81
 
79
82
  call_state_entry_callback(args[:trigger], old_state) if current_state_def.has_entry_callback?
80
83
 
81
- @subject.instance_exec(old_state, @current_state, args[:trigger].to_sym, (Time.now - _start), &state_machine_definition.on_transition_proc) if state_machine_definition.has_on_transition_proc?
84
+ self.instance_exec(old_state, current_state, args[:trigger].to_sym, (Time.now - _start), &state_machine_definition.on_transition_proc) if state_machine_definition.has_on_transition_proc?
85
+
82
86
  true
83
87
  end
84
88
 
@@ -105,5 +109,4 @@ module StateShifter
105
109
 
106
110
  end
107
111
  end
108
-
109
112
  end
data/lib/state_shifter.rb CHANGED
@@ -4,9 +4,6 @@ require 'state_shifter/definition'
4
4
  require 'state_shifter/definition/contents'
5
5
  require 'state_shifter/definition/class_methods'
6
6
  require 'state_shifter/definition/instance_methods'
7
- require 'state_shifter/mountable'
8
- require 'state_shifter/mountable/class_methods'
9
- require 'state_shifter/mountable/instance_methods'
10
7
 
11
8
  class ::StateShifter::TransitionHalted < Exception ; end
12
9
  class ::StateShifter::GuardMethodUndefined < Exception ; end
@@ -14,4 +11,5 @@ class ::StateShifter::GuardNotSatisfied < Exception ; end
14
11
  class ::StateShifter::CallbackMethodNotDefined < Exception ; end
15
12
  class ::StateShifter::RedifiningEvent < Exception ; end
16
13
  class ::StateShifter::RedifiningState < Exception ; end
14
+ class ::StateShifter::PersistenceAttributeAlreadyDefined < Exception ; end
17
15
 
data/spec/spec_helper.rb CHANGED
@@ -1,10 +1,14 @@
1
1
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
2
  $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+
3
4
  require 'rspec'
5
+ require 'active_record'
6
+
4
7
  require 'state_shifter'
5
- require 'simplecov'
6
8
 
7
9
  if ENV['COVERAGE']
10
+ require 'simplecov'
11
+
8
12
  SimpleCov.start do
9
13
  add_filter 'spec'
10
14
  end
@@ -1,7 +1,6 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
  require_relative '../examples/simple'
3
3
  require_relative '../examples/advanced'
4
- require_relative '../examples/mounted'
5
4
 
6
5
  shared_examples_for 'a simple state machine' do
7
6
 
@@ -101,12 +100,6 @@ describe Simple do
101
100
 
102
101
  end
103
102
 
104
- describe Mounted do
105
-
106
- it_should_behave_like 'a simple state machine'
107
-
108
- end
109
-
110
103
  describe 'Malformed state machines' do
111
104
 
112
105
  it 'should complain about redifining states' do
@@ -117,6 +110,18 @@ describe 'Malformed state machines' do
117
110
  lambda { require_relative '../examples/malformed_events' }.should raise_error(StateShifter::RedifiningEvent, 'submit')
118
111
  end
119
112
 
113
+ it 'should complain when the persistence attribute is set after the state machine definition' do
114
+ lambda { require_relative '../examples/malformed_persistence' }.should raise_error(StateShifter::PersistenceAttributeAlreadyDefined)
115
+ end
116
+
117
+ end
118
+
119
+ describe 'Advanced state machine functionality' do
120
+
121
+ before(:each) do
122
+ @advanced = Advanced.new
123
+ end
124
+
120
125
  it 'should complain about undefined guards' do
121
126
  advanced = Advanced.new
122
127
  lambda { advanced.can_start_date_reached?}.should raise_error(StateShifter::GuardMethodUndefined, 'start_date_reached?')
@@ -129,14 +134,6 @@ describe 'Malformed state machines' do
129
134
  lambda { advanced.deadline_reached }.should raise_error(StateShifter::CallbackMethodNotDefined, 'send_notification_to_organizers')
130
135
  end
131
136
 
132
- end
133
-
134
- describe 'Advanced state machine functionality' do
135
-
136
- before(:each) do
137
- @advanced = Advanced.new
138
- end
139
-
140
137
  it 'should complain about looping event callbacks not being defined' do
141
138
  lambda { @advanced.start_date_changed }.should raise_error(StateShifter::CallbackMethodNotDefined, 'handle_start_date_changed')
142
139
  end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "state_shifter"
8
- s.version = "0.7.1"
8
+ s.version = "0.7.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Bruno Antunes"]
12
- s.date = "2012-08-24"
12
+ s.date = "2012-08-27"
13
13
  s.description = "state_shifter is a gem that adds state machine behavior to a class"
14
14
  s.email = "sardaukar.siet@gmail.com"
15
15
  s.extra_rdoc_files = [
@@ -27,8 +27,8 @@ Gem::Specification.new do |s|
27
27
  "VERSION",
28
28
  "examples/advanced.rb",
29
29
  "examples/malformed_events.rb",
30
+ "examples/malformed_persistence.rb",
30
31
  "examples/malformed_states.rb",
31
- "examples/mounted.rb",
32
32
  "examples/simple.rb",
33
33
  "lib/state_shifter.rb",
34
34
  "lib/state_shifter/definition.rb",
@@ -36,9 +36,6 @@ Gem::Specification.new do |s|
36
36
  "lib/state_shifter/definition/contents.rb",
37
37
  "lib/state_shifter/definition/instance_methods.rb",
38
38
  "lib/state_shifter/event.rb",
39
- "lib/state_shifter/mountable.rb",
40
- "lib/state_shifter/mountable/class_methods.rb",
41
- "lib/state_shifter/mountable/instance_methods.rb",
42
39
  "lib/state_shifter/state.rb",
43
40
  "spec/spec_helper.rb",
44
41
  "spec/state_shifter_spec.rb",
@@ -54,6 +51,7 @@ Gem::Specification.new do |s|
54
51
  s.specification_version = 3
55
52
 
56
53
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
54
+ s.add_development_dependency(%q<activerecord>, ["~> 3.2.x"])
57
55
  s.add_development_dependency(%q<rspec>, ["~> 2.8.0"])
58
56
  s.add_development_dependency(%q<yard>, ["~> 0.7"])
59
57
  s.add_development_dependency(%q<redcarpet>, [">= 0"])
@@ -62,6 +60,7 @@ Gem::Specification.new do |s|
62
60
  s.add_development_dependency(%q<jeweler>, ["~> 1.8.4"])
63
61
  s.add_development_dependency(%q<simplecov>, [">= 0"])
64
62
  else
63
+ s.add_dependency(%q<activerecord>, ["~> 3.2.x"])
65
64
  s.add_dependency(%q<rspec>, ["~> 2.8.0"])
66
65
  s.add_dependency(%q<yard>, ["~> 0.7"])
67
66
  s.add_dependency(%q<redcarpet>, [">= 0"])
@@ -71,6 +70,7 @@ Gem::Specification.new do |s|
71
70
  s.add_dependency(%q<simplecov>, [">= 0"])
72
71
  end
73
72
  else
73
+ s.add_dependency(%q<activerecord>, ["~> 3.2.x"])
74
74
  s.add_dependency(%q<rspec>, ["~> 2.8.0"])
75
75
  s.add_dependency(%q<yard>, ["~> 0.7"])
76
76
  s.add_dependency(%q<redcarpet>, [">= 0"])
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: state_shifter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.7.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,8 +9,24 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-24 00:00:00.000000000 Z
12
+ date: 2012-08-27 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activerecord
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 3.2.x
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 3.2.x
14
30
  - !ruby/object:Gem::Dependency
15
31
  name: rspec
16
32
  requirement: !ruby/object:Gem::Requirement
@@ -141,8 +157,8 @@ files:
141
157
  - VERSION
142
158
  - examples/advanced.rb
143
159
  - examples/malformed_events.rb
160
+ - examples/malformed_persistence.rb
144
161
  - examples/malformed_states.rb
145
- - examples/mounted.rb
146
162
  - examples/simple.rb
147
163
  - lib/state_shifter.rb
148
164
  - lib/state_shifter/definition.rb
@@ -150,9 +166,6 @@ files:
150
166
  - lib/state_shifter/definition/contents.rb
151
167
  - lib/state_shifter/definition/instance_methods.rb
152
168
  - lib/state_shifter/event.rb
153
- - lib/state_shifter/mountable.rb
154
- - lib/state_shifter/mountable/class_methods.rb
155
- - lib/state_shifter/mountable/instance_methods.rb
156
169
  - lib/state_shifter/state.rb
157
170
  - spec/spec_helper.rb
158
171
  - spec/state_shifter_spec.rb
@@ -172,7 +185,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
172
185
  version: '0'
173
186
  segments:
174
187
  - 0
175
- hash: -1507395421623075771
188
+ hash: -2788732275758639550
176
189
  required_rubygems_version: !ruby/object:Gem::Requirement
177
190
  none: false
178
191
  requirements:
data/examples/mounted.rb DELETED
@@ -1,8 +0,0 @@
1
- require_relative 'simple'
2
-
3
- class Mounted
4
- include StateShifter::Mountable
5
-
6
- mount_state_machine Simple
7
-
8
- end
@@ -1,13 +0,0 @@
1
- module StateShifter
2
- module Mountable
3
- module ClassMethods
4
-
5
- attr_accessor :mountable_class_name
6
-
7
- def mount_state_machine mountable_class_name
8
- self.mountable_class_name = mountable_class_name
9
- end
10
-
11
- end
12
- end
13
- end
@@ -1,20 +0,0 @@
1
- module StateShifter
2
- module Mountable
3
- module InstanceMethods
4
-
5
- attr_accessor :state_machine_definition
6
-
7
- def initialize
8
- @state_machine_definition = self.class.mountable_class_name.new
9
- @state_machine_definition.instance_variable_set(:@subject,self)
10
-
11
- ( @state_machine_definition.methods - Object.methods).sort.each do |meth|
12
- self.class.send :define_method, meth, &@state_machine_definition.method(meth)
13
- end
14
-
15
- super
16
- end
17
-
18
- end
19
- end
20
- end
@@ -1,10 +0,0 @@
1
- module StateShifter
2
- module Mountable
3
-
4
- def self.included klass
5
- klass.send :include, InstanceMethods
6
- klass.extend ClassMethods
7
- end
8
-
9
- end
10
- end