dm-is-persistent_state_machine 0.0.2 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.2
1
+ 0.1.0
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{dm-is-persistent_state_machine}
8
- s.version = "0.0.2"
8
+ s.version = "0.1.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["michael"]
12
- s.date = %q{2010-01-04}
12
+ s.date = %q{2010-01-14}
13
13
  s.description = %q{A persistent State Machine for DataMapper}
14
14
  s.email = %q{ma@zive.at}
15
15
  s.extra_rdoc_files = [
@@ -26,8 +26,10 @@ Gem::Specification.new do |s|
26
26
  "dm-is-persistent_state_machine.gemspec",
27
27
  "lib/dm-is-persistent_state_machine.rb",
28
28
  "lib/dm-is-persistent_state_machine/is/persistent_state_machine.rb",
29
- "test/helper.rb",
30
- "test/test_dm-is-persistent_state_machine.rb"
29
+ "spec/dm-is-persistent_state_machine_spec.rb",
30
+ "spec/rcov.opts",
31
+ "spec/spec.opts",
32
+ "spec/spec_helper.rb"
31
33
  ]
32
34
  s.homepage = %q{http://github.com/michael/dm-is-persistent_state_machine}
33
35
  s.rdoc_options = ["--charset=UTF-8"]
@@ -35,8 +37,8 @@ Gem::Specification.new do |s|
35
37
  s.rubygems_version = %q{1.3.5}
36
38
  s.summary = %q{A persistent State Machine for DataMapper}
37
39
  s.test_files = [
38
- "test/helper.rb",
39
- "test/test_dm-is-persistent_state_machine.rb"
40
+ "spec/dm-is-persistent_state_machine_spec.rb",
41
+ "spec/spec_helper.rb"
40
42
  ]
41
43
 
42
44
  if s.respond_to? :specification_version then
@@ -15,12 +15,12 @@ end
15
15
  class State
16
16
  include DataMapper::Resource
17
17
 
18
- property :id, Serial
19
- property :code, String, :required => true, :unique => true, :unique_index => true
20
- property :name, String, :required => true, :unique => true, :unique_index => true
21
- property :editable, Boolean
22
- property :sorter, Integer
23
- property :type, Discriminator
18
+ property :id, Serial
19
+ property :code, String, :required => true, :unique => true, :unique_index => true
20
+ property :name, String, :required => true, :unique => true, :unique_index => true
21
+ property :editable, Boolean, :default => true
22
+ property :sorter, Integer
23
+ property :type, Discriminator
24
24
 
25
25
  # outgoing transitions
26
26
  has n, :state_transitions, 'StateTransition', :child_key => [:state_id]
@@ -51,12 +51,26 @@ end
51
51
  class StateEvent
52
52
  include DataMapper::Resource
53
53
 
54
- property :id, Serial
54
+ property :id, Serial
55
55
  property :code, String, :required => true, :unique => true, :unique_index => true
56
56
  property :name, String, :required => true, :unique => true, :unique_index => true
57
57
  property :type, Discriminator
58
58
  end
59
59
 
60
+ class StateChange
61
+ include DataMapper::Resource
62
+
63
+ property :id, Serial
64
+
65
+ property :from_id, Integer, :required => true, :min => 1, :unique_index => :type
66
+ property :to_id, Integer, :required => true, :min => 1, :unique_index => :type
67
+
68
+ property :created_at, DateTime
69
+
70
+ # associations
71
+ belongs_to :from, "State"
72
+ belongs_to :to, "State"
73
+ end
60
74
 
61
75
  module DataMapper
62
76
  module Is
@@ -79,7 +93,8 @@ module DataMapper
79
93
  ##
80
94
 
81
95
  def is_persistent_state_machine
82
-
96
+ DataMapper.logger.info "registering persistent state machine..."
97
+
83
98
  # Add class-methods
84
99
  extend DataMapper::Is::PersistentStateMachine::ClassMethods
85
100
  extend Forwardable
@@ -90,32 +105,41 @@ module DataMapper
90
105
  property :state_id, Integer, :required => true, :min => 1
91
106
  belongs_to :state
92
107
 
93
- DataMapper.logger.info "registering persistent state machine..."
94
-
95
- # define delegators
96
- def_delegators :@state, :events
97
-
98
108
  # generate a FooState class that is derived from State
99
109
  state_model = Object.full_const_set(self.to_s+"State", Class.new(State))
100
110
  # generate a FooStateEvent class that is derived from StateEvent
101
111
  event_model = Object.full_const_set(self.to_s+"StateEvent", Class.new(StateEvent))
112
+
113
+ after :save do
114
+ if (@prev_state && @prev_state != state)
115
+ StateChange.create(:from => @prev_state, :to => state, :created_at => DateTime.now)
116
+ end
117
+ end
118
+
119
+ # define delegators
120
+ def_delegators :@state, :events
102
121
  end
103
122
 
104
123
  ##
105
124
  # fired after trigger_event! is called on resource
106
125
  #
107
- def after_trigger_event(event)
108
- end
109
-
110
126
  module ClassMethods
111
127
 
112
128
  end # ClassMethods
113
129
 
114
130
  module InstanceMethods
115
- def trigger_event!(event_code)
131
+ def trigger_event!(event_code)
132
+ # cache the old value
133
+ @prev_state = self.state
134
+
116
135
  # delegate to State#trigger!
117
136
  self.state.trigger_event!(self, event_code)
118
137
  end
138
+
139
+ # hookable
140
+ def after_trigger_event(event)
141
+
142
+ end
119
143
  end # InstanceMethods
120
144
  end # PersistentStateMachine
121
145
  end # Is
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe DataMapper::Is::PersistentStateMachine do
4
+
5
+ before(:all) do
6
+ DataMapper.auto_migrate!
7
+
8
+ # add some states
9
+ open = ProjectState.create(:name => "Open", :code => "open")
10
+ reviewed = ProjectState.create(:name => "Reviewed", :code => "reviewed")
11
+ confirmed = ProjectState.create(:name => "Confirmed", :code => "confirmed")
12
+
13
+ # add some events
14
+ review_evt = ProjectStateEvent.create(:code => "review", :name => "Review")
15
+ confirm_evt = ProjectStateEvent.create(:code => "confirm", :name => "Confirm")
16
+
17
+ # add some transitions
18
+ open_reviewed = StateTransition.create(:state => open, :target => reviewed, :state_event => review_evt)
19
+ reviewed_confirmed = StateTransition.create(:state => reviewed, :target => confirmed, :state_event => confirm_evt)
20
+ end
21
+
22
+ describe "with active DM Identity Map" do
23
+
24
+ before :each do
25
+ Project.auto_migrate!
26
+ StateChange.auto_migrate!
27
+ end
28
+
29
+ it "should log state changes" do
30
+ @project = Project.create(:name => "Operation X", :state => ProjectState.first(:code => "open"))
31
+ @project.state.code.should == "open"
32
+ @project.trigger_event!('review')
33
+ Project.first(:name => "Operation X").state.code.should == "open" # not persistent yet
34
+
35
+ StateChange.count.should == 0
36
+ @project.state.code.should == "reviewed"
37
+ @project.save
38
+ StateChange.count.should == 1
39
+ end
40
+ end
41
+ end
data/spec/rcov.opts ADDED
@@ -0,0 +1,6 @@
1
+ --exclude "spec"
2
+ --sort coverage
3
+ --callsites
4
+ --xrefs
5
+ --profile
6
+ --text-summary
data/spec/spec.opts ADDED
@@ -0,0 +1,4 @@
1
+ --colour
2
+ --loadby random
3
+ --format specdoc
4
+ --backtrace
@@ -0,0 +1,24 @@
1
+ require 'rubygems'
2
+
3
+ require 'dm-core'
4
+ require 'dm-adjust'
5
+ require 'dm-aggregates'
6
+ require 'dm-types'
7
+ require 'dm-validations'
8
+
9
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
10
+
11
+ require 'dm-is-persistent_state_machine'
12
+
13
+ DataMapper.setup(:default, 'sqlite3::memory:')
14
+
15
+ # classes/vars for tests
16
+
17
+ class Project
18
+ include DataMapper::Resource
19
+
20
+ property :id, Serial
21
+ property :name, String
22
+
23
+ is :persistent_state_machine
24
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dm-is-persistent_state_machine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - michael
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-01-04 00:00:00 +01:00
12
+ date: 2010-01-14 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -41,8 +41,10 @@ files:
41
41
  - dm-is-persistent_state_machine.gemspec
42
42
  - lib/dm-is-persistent_state_machine.rb
43
43
  - lib/dm-is-persistent_state_machine/is/persistent_state_machine.rb
44
- - test/helper.rb
45
- - test/test_dm-is-persistent_state_machine.rb
44
+ - spec/dm-is-persistent_state_machine_spec.rb
45
+ - spec/rcov.opts
46
+ - spec/spec.opts
47
+ - spec/spec_helper.rb
46
48
  has_rdoc: true
47
49
  homepage: http://github.com/michael/dm-is-persistent_state_machine
48
50
  licenses: []
@@ -72,5 +74,5 @@ signing_key:
72
74
  specification_version: 3
73
75
  summary: A persistent State Machine for DataMapper
74
76
  test_files:
75
- - test/helper.rb
76
- - test/test_dm-is-persistent_state_machine.rb
77
+ - spec/dm-is-persistent_state_machine_spec.rb
78
+ - spec/spec_helper.rb
data/test/helper.rb DELETED
@@ -1,10 +0,0 @@
1
- require 'rubygems'
2
- require 'test/unit'
3
- require 'shoulda'
4
-
5
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
- $LOAD_PATH.unshift(File.dirname(__FILE__))
7
- require 'dm-is-persistent_state_machine'
8
-
9
- class Test::Unit::TestCase
10
- end
@@ -1,7 +0,0 @@
1
- require 'helper'
2
-
3
- class TestDmIsPersistentStateMachine < Test::Unit::TestCase
4
- should "probably rename this file and start testing for real" do
5
- flunk "hey buddy, you should probably rename this file and start testing for real"
6
- end
7
- end