state_shifter 0.7.2 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -7,6 +7,7 @@ source "http://rubygems.org"
7
7
  # Include everything needed to run rake, tests, features, etc.
8
8
  group :development do
9
9
  gem 'activerecord', '~> 3.2.x'
10
+ gem 'sqlite3'
10
11
  gem "rspec", "~> 2.8.0"
11
12
  gem "yard", "~> 0.7"
12
13
  gem 'redcarpet'
data/Gemfile.lock CHANGED
@@ -40,6 +40,7 @@ GEM
40
40
  multi_json (~> 1.0)
41
41
  simplecov-html (~> 0.5.3)
42
42
  simplecov-html (0.5.3)
43
+ sqlite3 (1.3.6)
43
44
  tzinfo (0.3.33)
44
45
  yard (0.8.2.1)
45
46
 
@@ -54,4 +55,5 @@ DEPENDENCIES
54
55
  redcarpet
55
56
  rspec (~> 2.8.0)
56
57
  simplecov
58
+ sqlite3
57
59
  yard (~> 0.7)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.7.2
1
+ 0.8.0
@@ -1,4 +1,4 @@
1
- class Advanced
1
+ class MalformedPersistence
2
2
  include StateShifter::Definition
3
3
 
4
4
  ###
@@ -0,0 +1,98 @@
1
+ class MissingPersistence < ActiveRecord::Base
2
+ include StateShifter::Definition
3
+
4
+ ###
5
+
6
+ persist_attribute :lollies
7
+
8
+ state_machine do
9
+
10
+ state :initialized do
11
+
12
+ event :start_date_changed, :call => :handle_start_date_changed
13
+ event :forced_start => :running
14
+ event :start_date_reached => :running, :if => :start_date_reached?
15
+ event :abort_initialized_contest => :finalized
16
+ end
17
+
18
+ state :running do
19
+
20
+ on_entry do |previous_state, trigger_event|
21
+ running_entry previous_state, trigger_event
22
+ end
23
+
24
+ event :abort_running_contest => :notify_stakeholders
25
+ event :changed_properties
26
+ event :keep_users_engaged
27
+ event :deadline_reached => :notify_organizers, :if => :entries_deadline_reached?
28
+ event :spots_filled => :notify_organizers, :if => :spots_filled?
29
+ event :deadline_reached_without_approvals => :notify_pending_users, :if => :entries_deadline_reached_without_approvals?
30
+ event :deadline_reached_without_entries => :finalized, :if => :entries_deadline_reached_without_entries?
31
+ end
32
+
33
+ state :notify_organizers do
34
+ on_entry :send_notification_to_organizers
35
+ event :organizers_notified => :awaiting_organizer_reply
36
+ end
37
+
38
+ state :awaiting_organizer_reply do
39
+ event :organizer_confirmation_missing => :notify_stakeholders, :if => :organizer_confirmation_deadline_reached?
40
+ event :keep_organizers_engaged
41
+ event :organizer_confirmation_received => :notify_approved_users
42
+ event :organizer_has_more_tickets => :running
43
+ end
44
+
45
+ state :notify_stakeholders do
46
+ on_entry :send_notification_to_stakeholders
47
+ event :stakeholders_notified => :cancelled
48
+ end
49
+
50
+ state :cancelled
51
+
52
+ state :notify_pending_users do
53
+ on_entry :send_notification_to_pending_users
54
+ event :pending_users_notified => :finalized
55
+ end
56
+
57
+ state :notify_approved_users do
58
+ on_entry :send_notification_to_approved_users
59
+ event :approved_users_notified => :send_list_to_organizers
60
+ end
61
+
62
+ state :send_list_to_organizers do
63
+ on_entry :send_guestlist_to_organizers
64
+ event :list_sent_to_organizers => :awaiting_attendance
65
+ end
66
+
67
+ state :awaiting_attendance do
68
+ event :remind_to_fill_in_report => :create_report_filling_requests
69
+ end
70
+
71
+ state :create_report_filling_requests do
72
+ on_entry :send_report_filling_requests
73
+ event :finalize => :finalized
74
+ end
75
+
76
+ state :finalized
77
+
78
+ on_transition do |from,to,trigger_event, duration|
79
+ benchmark from, to, trigger_event, duration
80
+ end
81
+ end
82
+
83
+
84
+ ###
85
+
86
+ def entries_deadline_reached?
87
+ true
88
+ end
89
+
90
+ def running_entry previous_state, trigger_event
91
+ #
92
+ end
93
+
94
+ def benchmark from, to, trigger_event, duration
95
+ #
96
+ end
97
+
98
+ end
@@ -0,0 +1,33 @@
1
+ class Review < ActiveRecord::Base
2
+ include StateShifter::Definition
3
+
4
+ state_machine do
5
+
6
+ # first state to be defined is the initial one
7
+ state :new do
8
+ event :submit => :awaiting_review
9
+ end
10
+
11
+ state :awaiting_review do
12
+ event :review => :being_reviewed
13
+ end
14
+
15
+ state :being_reviewed do
16
+ event :accept => :accepted, :if => :cool_article?
17
+ event :reject => :rejected, :if => :bad_article?
18
+ end
19
+
20
+ state :accepted
21
+ state :rejected
22
+
23
+ end
24
+
25
+ def cool_article?
26
+ true
27
+ end
28
+
29
+ def bad_article?
30
+ false
31
+ end
32
+
33
+ end
@@ -0,0 +1,35 @@
1
+ class ReviewCustomPersistence < ActiveRecord::Base
2
+ include StateShifter::Definition
3
+
4
+ persist_attribute :stamp
5
+
6
+ state_machine do
7
+
8
+ # first state to be defined is the initial one
9
+ state :new do
10
+ event :submit => :awaiting_review
11
+ end
12
+
13
+ state :awaiting_review do
14
+ event :review => :being_reviewed
15
+ end
16
+
17
+ state :being_reviewed do
18
+ event :accept => :accepted, :if => :cool_article?
19
+ event :reject => :rejected, :if => :bad_article?
20
+ end
21
+
22
+ state :accepted
23
+ state :rejected
24
+
25
+ end
26
+
27
+ def cool_article?
28
+ true
29
+ end
30
+
31
+ def bad_article?
32
+ false
33
+ end
34
+
35
+ end
@@ -0,0 +1,24 @@
1
+ module StateShifter
2
+ module Definition
3
+ module ActiveRecordIntegrationMethods
4
+
5
+ class ::StateShifter::Definition::StatePersistenceAttributeNotPresent < RuntimeError; end
6
+
7
+ def get_current_state
8
+ raise StatePersistenceAttributeNotPresent unless self.attribute_names.include? self.class.persist_attr_name.to_s
9
+ read_attribute self.class.persist_attr_name
10
+ end
11
+
12
+ def set_current_state value
13
+ raise StatePersistenceAttributeNotPresent unless self.attribute_names.include? self.class.persist_attr_name.to_s
14
+ update_attribute self.class.persist_attr_name, value
15
+ end
16
+
17
+ def write_initial_state
18
+ raise StatePersistenceAttributeNotPresent unless self.attribute_names.include? self.class.persist_attr_name.to_s
19
+ write_attribute self.class.persist_attr_name, self.class.state_machine_definition.initial_state.name.to_sym
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -3,7 +3,7 @@ module StateShifter
3
3
  module InstanceMethods
4
4
 
5
5
  def current_state
6
- @current_state ||= get_current_state
6
+ get_current_state
7
7
  end
8
8
 
9
9
  def get_current_state
@@ -19,11 +19,11 @@ module StateShifter
19
19
  end
20
20
 
21
21
  def next_states
22
- _next_states current_state
22
+ _next_states get_current_state
23
23
  end
24
24
 
25
25
  def transitionable_states
26
- _next_states current_state, {:check_guards => true}
26
+ _next_states get_current_state, {:check_guards => true}
27
27
  end
28
28
 
29
29
  def state_names
@@ -52,7 +52,7 @@ module StateShifter
52
52
  end
53
53
 
54
54
  def current_state_def
55
- state_machine_definition.get(:state, current_state)
55
+ state_machine_definition.get(:state, get_current_state)
56
56
  end
57
57
 
58
58
  def call_state_entry_callback trigger, old_state
@@ -73,7 +73,7 @@ module StateShifter
73
73
  _start = Time.now
74
74
 
75
75
  # BOOP!
76
- old_state = current_state
76
+ old_state = get_current_state
77
77
  set_current_state args[:to].to_sym
78
78
  #
79
79
 
@@ -81,7 +81,7 @@ module StateShifter
81
81
 
82
82
  call_state_entry_callback(args[:trigger], old_state) if current_state_def.has_entry_callback?
83
83
 
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?
84
+ self.instance_exec(old_state, get_current_state, args[:trigger].to_sym, (Time.now - _start), &state_machine_definition.on_transition_proc) if state_machine_definition.has_on_transition_proc?
85
85
 
86
86
  true
87
87
  end
@@ -4,6 +4,13 @@ module StateShifter
4
4
  def self.included klass
5
5
  klass.send :include, InstanceMethods
6
6
  klass.extend ClassMethods
7
+
8
+ if Object.const_defined?(:ActiveRecord)
9
+ if klass < ActiveRecord::Base
10
+ klass.send :include, ActiveRecordIntegrationMethods
11
+ klass.before_validation :write_initial_state
12
+ end
13
+ end
7
14
  end
8
15
 
9
16
  end
data/lib/state_shifter.rb CHANGED
@@ -4,6 +4,7 @@ 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/definition/active_record_integration_methods'
7
8
 
8
9
  class ::StateShifter::TransitionHalted < Exception ; end
9
10
  class ::StateShifter::GuardMethodUndefined < Exception ; end
@@ -1,11 +1,14 @@
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/review'
5
+ require_relative '../examples/review_custom_persistence'
4
6
 
5
7
  shared_examples_for 'a simple state machine' do
6
8
 
7
9
  before(:each) do
8
10
  @state_machine = described_class.new
11
+ @state_machine.save if @state_machine.class < ActiveRecord::Base
9
12
  end
10
13
 
11
14
  it 'should have all states and events defined' do
@@ -19,6 +22,7 @@ shared_examples_for 'a simple state machine' do
19
22
 
20
23
  @state_machine.submit
21
24
  @state_machine.initial_state.should == :new
25
+
22
26
  @state_machine.current_state.should == :awaiting_review
23
27
  end
24
28
 
@@ -162,3 +166,60 @@ describe 'Advanced state machine functionality' do
162
166
 
163
167
  end
164
168
 
169
+ describe Review do
170
+
171
+ before(:all) do
172
+ ActiveRecord::Migration.verbose = false
173
+
174
+ ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => ':memory:'
175
+
176
+ ActiveRecord::Schema.define do
177
+ create_table :reviews do |t|
178
+ t.string :current_state
179
+ end
180
+ end
181
+ end
182
+
183
+ it_should_behave_like 'a simple state machine'
184
+
185
+ end
186
+
187
+ describe ReviewCustomPersistence do
188
+
189
+ before(:all) do
190
+ ActiveRecord::Migration.verbose = false
191
+
192
+ ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => ':memory:'
193
+
194
+ ActiveRecord::Schema.define do
195
+ create_table :review_custom_persistences do |t|
196
+ t.string :stamp
197
+ end
198
+ end
199
+ end
200
+
201
+ it_should_behave_like 'a simple state machine'
202
+
203
+ end
204
+
205
+ describe 'Malformed persistence definition' do
206
+
207
+ before(:all) do
208
+ ActiveRecord::Migration.verbose = false
209
+
210
+ ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => ':memory:'
211
+
212
+ ActiveRecord::Schema.define do
213
+ create_table :missing_persistences do |t|
214
+ t.string :xyz
215
+ end
216
+ end
217
+ end
218
+
219
+ it 'should complain when the persist attribute is not present' do
220
+ require_relative '../examples/missing_persistence'
221
+ review_custom_persistence = MissingPersistence.new
222
+ lambda { review_custom_persistence.save }.should raise_error(StateShifter::Definition::StatePersistenceAttributeNotPresent)
223
+ end
224
+
225
+ end
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "state_shifter"
8
- s.version = "0.7.2"
8
+ s.version = "0.8.0"
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"]
@@ -29,9 +29,13 @@ Gem::Specification.new do |s|
29
29
  "examples/malformed_events.rb",
30
30
  "examples/malformed_persistence.rb",
31
31
  "examples/malformed_states.rb",
32
+ "examples/missing_persistence.rb",
33
+ "examples/review.rb",
34
+ "examples/review_custom_persistence.rb",
32
35
  "examples/simple.rb",
33
36
  "lib/state_shifter.rb",
34
37
  "lib/state_shifter/definition.rb",
38
+ "lib/state_shifter/definition/active_record_integration_methods.rb",
35
39
  "lib/state_shifter/definition/class_methods.rb",
36
40
  "lib/state_shifter/definition/contents.rb",
37
41
  "lib/state_shifter/definition/instance_methods.rb",
@@ -52,6 +56,7 @@ Gem::Specification.new do |s|
52
56
 
53
57
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
54
58
  s.add_development_dependency(%q<activerecord>, ["~> 3.2.x"])
59
+ s.add_development_dependency(%q<sqlite3>, [">= 0"])
55
60
  s.add_development_dependency(%q<rspec>, ["~> 2.8.0"])
56
61
  s.add_development_dependency(%q<yard>, ["~> 0.7"])
57
62
  s.add_development_dependency(%q<redcarpet>, [">= 0"])
@@ -61,6 +66,7 @@ Gem::Specification.new do |s|
61
66
  s.add_development_dependency(%q<simplecov>, [">= 0"])
62
67
  else
63
68
  s.add_dependency(%q<activerecord>, ["~> 3.2.x"])
69
+ s.add_dependency(%q<sqlite3>, [">= 0"])
64
70
  s.add_dependency(%q<rspec>, ["~> 2.8.0"])
65
71
  s.add_dependency(%q<yard>, ["~> 0.7"])
66
72
  s.add_dependency(%q<redcarpet>, [">= 0"])
@@ -71,6 +77,7 @@ Gem::Specification.new do |s|
71
77
  end
72
78
  else
73
79
  s.add_dependency(%q<activerecord>, ["~> 3.2.x"])
80
+ s.add_dependency(%q<sqlite3>, [">= 0"])
74
81
  s.add_dependency(%q<rspec>, ["~> 2.8.0"])
75
82
  s.add_dependency(%q<yard>, ["~> 0.7"])
76
83
  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.2
4
+ version: 0.8.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -27,6 +27,22 @@ dependencies:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
29
  version: 3.2.x
30
+ - !ruby/object:Gem::Dependency
31
+ name: sqlite3
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
30
46
  - !ruby/object:Gem::Dependency
31
47
  name: rspec
32
48
  requirement: !ruby/object:Gem::Requirement
@@ -159,9 +175,13 @@ files:
159
175
  - examples/malformed_events.rb
160
176
  - examples/malformed_persistence.rb
161
177
  - examples/malformed_states.rb
178
+ - examples/missing_persistence.rb
179
+ - examples/review.rb
180
+ - examples/review_custom_persistence.rb
162
181
  - examples/simple.rb
163
182
  - lib/state_shifter.rb
164
183
  - lib/state_shifter/definition.rb
184
+ - lib/state_shifter/definition/active_record_integration_methods.rb
165
185
  - lib/state_shifter/definition/class_methods.rb
166
186
  - lib/state_shifter/definition/contents.rb
167
187
  - lib/state_shifter/definition/instance_methods.rb
@@ -185,7 +205,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
185
205
  version: '0'
186
206
  segments:
187
207
  - 0
188
- hash: -2788732275758639550
208
+ hash: 3920605756095371187
189
209
  required_rubygems_version: !ruby/object:Gem::Requirement
190
210
  none: false
191
211
  requirements: