state_machine-audit_trail 0.1.5 → 0.1.6
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.
- checksums.yaml +15 -0
- data/README.rdoc +1 -1
- data/lib/state_machine/audit_trail/backend/active_record.rb +10 -3
- data/lib/state_machine/audit_trail/backend/mongoid.rb +1 -1
- data/lib/state_machine/audit_trail/transition_auditing.rb +5 -3
- data/lib/state_machine/audit_trail/version.rb +1 -1
- data/spec/helpers/active_record.rb +36 -1
- data/spec/state_machine/active_record_spec.rb +38 -4
- metadata +6 -21
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
OWM5NDNmMjY4ZDAyZjkxNzhjNWVmZGMxM2ZlNDNkN2ViZTJmZjY1Zg==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
Y2JlMTdiOWExODEyNTM5ZGY4MzFhMGRjMGY0OTNjZDNhYzQyNjMzZA==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
M2U0MzBiN2MxNDc3Y2E3YTczZDg0Mjc4NjkxOWQwNDcwZjlmODU1Yjg5ZmVk
|
10
|
+
OTc1YjI0OTc1YzZkMjJhZWZiNzE5Njg2YzdhNjhmM2IzYTIzZjIwMDg3NWYz
|
11
|
+
NzljOTk3NWZkZThlODVlZDQyMWMxZjRjZGNmZjg2Zjg2MWU5NWE=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
NzM5ODc4ZGIwNGY5YmE5NzU0YjZiOTNhZTM2MjA2NzQzZmM1ZWUyNWNmMWJl
|
14
|
+
ODU1OTU1Yzk3ZjIyN2ZjZGYwMDI2YTdkNDU1Y2U1MjJlYWNjMmNkZDMxMWI0
|
15
|
+
MTI3MDdjOTM2YmY1OTNjNzg3MjNkNDViZjBiNTg4NzUyNDhlZjA=
|
data/README.rdoc
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
= StateMachine audit trail
|
1
|
+
= StateMachine audit trail {<img src="https://travis-ci.org/wvanbergen/state_machine-audit_trail.png" />}[https://travis-ci.org/wvanbergen/state_machine-audit_trail]
|
2
2
|
|
3
3
|
This plugin for the state machine gem (see https://github.com/pluginaweek/state_machine) adds support for keeping an audit trail for any state machine. Having an audit trail gives you a complete history of the state changes in your model. This history allows you to investigate incidents or perform analytics, like: "How long does it take on average to go from state a to state b?", or "What percentage of cases goes from state a to b via state c?"
|
4
4
|
|
@@ -3,9 +3,9 @@ class StateMachine::AuditTrail::Backend::ActiveRecord < StateMachine::AuditTrail
|
|
3
3
|
|
4
4
|
def initialize(transition_class, owner_class, context_to_log = nil)
|
5
5
|
self.context_to_log = context_to_log
|
6
|
-
@association = transition_class.to_s.tableize.to_sym
|
6
|
+
@association = transition_class.to_s.tableize.split('/').last.to_sym
|
7
7
|
super transition_class
|
8
|
-
owner_class.has_many @association
|
8
|
+
owner_class.has_many(@association, :class_name => transition_class.to_s) unless owner_class.reflect_on_association(@association)
|
9
9
|
end
|
10
10
|
|
11
11
|
def log(object, event, from, to, timestamp = Time.now)
|
@@ -13,6 +13,13 @@ class StateMachine::AuditTrail::Backend::ActiveRecord < StateMachine::AuditTrail
|
|
13
13
|
# right thing with regards to timezones.
|
14
14
|
params = {:event => event, :from => from, :to => to}
|
15
15
|
params[self.context_to_log] = object.send(self.context_to_log) unless self.context_to_log.nil?
|
16
|
-
|
16
|
+
|
17
|
+
if object.new_record?
|
18
|
+
object.send(@association).build(params)
|
19
|
+
else
|
20
|
+
object.send(@association).create(params)
|
21
|
+
end
|
22
|
+
|
23
|
+
nil
|
17
24
|
end
|
18
25
|
end
|
@@ -12,7 +12,7 @@ class StateMachine::AuditTrail::Backend::Mongoid < StateMachine::AuditTrail::Bac
|
|
12
12
|
def log(object, event, from, to, timestamp = Time.now)
|
13
13
|
tc = transition_class
|
14
14
|
foreign_key_field = tc.relations.keys.first
|
15
|
-
transition_class.create(foreign_key_field => object, :event => event, :from => from, :to => to, :
|
15
|
+
transition_class.create(foreign_key_field => object, :event => event, :from => from, :to => to, :created_at => timestamp)
|
16
16
|
end
|
17
17
|
|
18
18
|
|
@@ -16,9 +16,11 @@ module StateMachine::AuditTrail::TransitionAuditing
|
|
16
16
|
state_machine.audit_trail(options[:context_to_log]).log(object, transition.event, transition.from, transition.to)
|
17
17
|
end
|
18
18
|
|
19
|
-
state_machine.
|
20
|
-
|
21
|
-
|
19
|
+
unless state_machine.action == nil
|
20
|
+
state_machine.owner_class.after_create do |object|
|
21
|
+
if !object.send(state_machine.attribute).nil?
|
22
|
+
state_machine.audit_trail(options[:context_to_log]).log(object, nil, nil, object.send(state_machine.attribute))
|
23
|
+
end
|
22
24
|
end
|
23
25
|
end
|
24
26
|
end
|
@@ -39,6 +39,10 @@ class ActiveRecordTestModelWithMultipleStateMachinesSecondTransition < ActiveRec
|
|
39
39
|
belongs_to :test_model
|
40
40
|
end
|
41
41
|
|
42
|
+
class ActiveRecordTestModelWithMultipleStateMachinesThirdTransition < ActiveRecord::Base
|
43
|
+
belongs_to :test_model
|
44
|
+
end
|
45
|
+
|
42
46
|
class ActiveRecordTestModel < ActiveRecord::Base
|
43
47
|
|
44
48
|
state_machine :state, :initial => :waiting do # log initial state?
|
@@ -102,8 +106,38 @@ class ActiveRecordTestModelWithMultipleStateMachines < ActiveRecord::Base
|
|
102
106
|
transition nil => :beginning_second
|
103
107
|
end
|
104
108
|
end
|
109
|
+
|
110
|
+
state_machine :third, :action => nil do
|
111
|
+
store_audit_trail
|
112
|
+
|
113
|
+
event :begin_third do
|
114
|
+
transition nil => :beginning_third
|
115
|
+
end
|
116
|
+
|
117
|
+
event :end_third do
|
118
|
+
transition :beginning_third => :done_third
|
119
|
+
end
|
120
|
+
end
|
105
121
|
end
|
106
122
|
|
123
|
+
module SomeNamespace
|
124
|
+
class ActiveRecordTestModel < ActiveRecord::Base
|
125
|
+
|
126
|
+
state_machine :state, :initial => :waiting do # log initial state?
|
127
|
+
store_audit_trail
|
128
|
+
|
129
|
+
event :start do
|
130
|
+
transition [:waiting, :stopped] => :started
|
131
|
+
end
|
132
|
+
|
133
|
+
event :stop do
|
134
|
+
transition :started => :stopped
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
|
107
141
|
def create_transition_table(owner_class, state, add_context = false)
|
108
142
|
class_name = "#{owner_class.name}#{state.to_s.camelize}Transition"
|
109
143
|
ActiveRecord::Base.connection.create_table(class_name.tableize) do |t|
|
@@ -119,4 +153,5 @@ end
|
|
119
153
|
create_transition_table(ActiveRecordTestModel, :state)
|
120
154
|
create_transition_table(ActiveRecordTestModelWithContext, :state, true)
|
121
155
|
create_transition_table(ActiveRecordTestModelWithMultipleStateMachines, :first)
|
122
|
-
create_transition_table(ActiveRecordTestModelWithMultipleStateMachines, :second)
|
156
|
+
create_transition_table(ActiveRecordTestModelWithMultipleStateMachines, :second)
|
157
|
+
create_transition_table(ActiveRecordTestModelWithMultipleStateMachines, :third)
|
@@ -13,9 +13,12 @@ describe StateMachine::AuditTrail::Backend::ActiveRecord do
|
|
13
13
|
ActiveRecordTestModel.reflect_on_association(:active_record_test_model_state_transitions).collection?.should be_true
|
14
14
|
end
|
15
15
|
|
16
|
-
|
17
|
-
|
16
|
+
it "should handle namespaced models" do
|
17
|
+
backend = StateMachine::AuditTrail::Backend.create_for_transition_class(ActiveRecordTestModelStateTransition, SomeNamespace::ActiveRecordTestModel)
|
18
|
+
SomeNamespace::ActiveRecordTestModel.reflect_on_association(:active_record_test_model_state_transitions).collection?.should be_true
|
19
|
+
end
|
18
20
|
|
21
|
+
shared_examples "a state machine audit trail" do
|
19
22
|
it "should log an event with all fields set correctly" do
|
20
23
|
state_machine.start!
|
21
24
|
last_transition = ActiveRecordTestModelStateTransition.where(:active_record_test_model_id => state_machine.id).last
|
@@ -27,12 +30,26 @@ describe StateMachine::AuditTrail::Backend::ActiveRecord do
|
|
27
30
|
last_transition.created_at.should be_within(10.seconds).of(Time.now.utc)
|
28
31
|
end
|
29
32
|
|
33
|
+
it "should do nothing when the transition is not executed successfully" do
|
34
|
+
lambda { state_machine.stop }.should_not change(ActiveRecordTestModelStateTransition, :count)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'on an existing object with a single state machine' do
|
39
|
+
let!(:state_machine) { ActiveRecordTestModel.create! }
|
40
|
+
include_examples "a state machine audit trail"
|
41
|
+
|
30
42
|
it "should log multiple events" do
|
31
43
|
lambda { state_machine.start && state_machine.stop && state_machine.start }.should change(ActiveRecordTestModelStateTransition, :count).by(3)
|
32
44
|
end
|
45
|
+
end
|
33
46
|
|
34
|
-
|
35
|
-
|
47
|
+
context 'on a new object with a single state machine' do
|
48
|
+
let!(:state_machine) { ActiveRecordTestModel.new }
|
49
|
+
include_examples "a state machine audit trail"
|
50
|
+
|
51
|
+
it "should log multiple events including the first event from save" do
|
52
|
+
lambda { state_machine.start && state_machine.stop && state_machine.start }.should change(ActiveRecordTestModelStateTransition, :count).by(4)
|
36
53
|
end
|
37
54
|
end
|
38
55
|
|
@@ -100,6 +117,23 @@ describe StateMachine::AuditTrail::Backend::ActiveRecord do
|
|
100
117
|
first_transition.to.should == 'beginning_second'
|
101
118
|
first_transition.created_at.should be_within(10.seconds).of(Time.now.utc)
|
102
119
|
end
|
120
|
+
|
121
|
+
it "should be fine transitioning before saved on an :action => nil state machine" do
|
122
|
+
lambda do
|
123
|
+
machine = state_machine_class.new
|
124
|
+
machine.begin_third
|
125
|
+
machine.save!
|
126
|
+
end.should change(ActiveRecordTestModelWithMultipleStateMachinesThirdTransition, :count).by(1)
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should queue up transitions to be saved before being saved on an :action => nil state machine" do
|
130
|
+
lambda do
|
131
|
+
machine = state_machine_class.new
|
132
|
+
machine.begin_third
|
133
|
+
machine.end_third
|
134
|
+
machine.save!
|
135
|
+
end.should change(ActiveRecordTestModelWithMultipleStateMachinesThirdTransition, :count).by(2)
|
136
|
+
end
|
103
137
|
end
|
104
138
|
|
105
139
|
context 'on a class using STI' do
|
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: state_machine-audit_trail
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
5
|
-
prerelease:
|
4
|
+
version: 0.1.6
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Willem van Bergen
|
@@ -10,12 +9,11 @@ authors:
|
|
10
9
|
autorequire:
|
11
10
|
bindir: bin
|
12
11
|
cert_chain: []
|
13
|
-
date: 2013-
|
12
|
+
date: 2013-12-10 00:00:00.000000000 Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: state_machine
|
17
16
|
requirement: !ruby/object:Gem::Requirement
|
18
|
-
none: false
|
19
17
|
requirements:
|
20
18
|
- - ! '>='
|
21
19
|
- !ruby/object:Gem::Version
|
@@ -23,7 +21,6 @@ dependencies:
|
|
23
21
|
type: :runtime
|
24
22
|
prerelease: false
|
25
23
|
version_requirements: !ruby/object:Gem::Requirement
|
26
|
-
none: false
|
27
24
|
requirements:
|
28
25
|
- - ! '>='
|
29
26
|
- !ruby/object:Gem::Version
|
@@ -31,7 +28,6 @@ dependencies:
|
|
31
28
|
- !ruby/object:Gem::Dependency
|
32
29
|
name: rake
|
33
30
|
requirement: !ruby/object:Gem::Requirement
|
34
|
-
none: false
|
35
31
|
requirements:
|
36
32
|
- - ! '>='
|
37
33
|
- !ruby/object:Gem::Version
|
@@ -39,7 +35,6 @@ dependencies:
|
|
39
35
|
type: :development
|
40
36
|
prerelease: false
|
41
37
|
version_requirements: !ruby/object:Gem::Requirement
|
42
|
-
none: false
|
43
38
|
requirements:
|
44
39
|
- - ! '>='
|
45
40
|
- !ruby/object:Gem::Version
|
@@ -47,7 +42,6 @@ dependencies:
|
|
47
42
|
- !ruby/object:Gem::Dependency
|
48
43
|
name: rspec
|
49
44
|
requirement: !ruby/object:Gem::Requirement
|
50
|
-
none: false
|
51
45
|
requirements:
|
52
46
|
- - ~>
|
53
47
|
- !ruby/object:Gem::Version
|
@@ -55,7 +49,6 @@ dependencies:
|
|
55
49
|
type: :development
|
56
50
|
prerelease: false
|
57
51
|
version_requirements: !ruby/object:Gem::Requirement
|
58
|
-
none: false
|
59
52
|
requirements:
|
60
53
|
- - ~>
|
61
54
|
- !ruby/object:Gem::Version
|
@@ -63,7 +56,6 @@ dependencies:
|
|
63
56
|
- !ruby/object:Gem::Dependency
|
64
57
|
name: activerecord
|
65
58
|
requirement: !ruby/object:Gem::Requirement
|
66
|
-
none: false
|
67
59
|
requirements:
|
68
60
|
- - ~>
|
69
61
|
- !ruby/object:Gem::Version
|
@@ -71,7 +63,6 @@ dependencies:
|
|
71
63
|
type: :development
|
72
64
|
prerelease: false
|
73
65
|
version_requirements: !ruby/object:Gem::Requirement
|
74
|
-
none: false
|
75
66
|
requirements:
|
76
67
|
- - ~>
|
77
68
|
- !ruby/object:Gem::Version
|
@@ -79,7 +70,6 @@ dependencies:
|
|
79
70
|
- !ruby/object:Gem::Dependency
|
80
71
|
name: sqlite3
|
81
72
|
requirement: !ruby/object:Gem::Requirement
|
82
|
-
none: false
|
83
73
|
requirements:
|
84
74
|
- - ! '>='
|
85
75
|
- !ruby/object:Gem::Version
|
@@ -87,7 +77,6 @@ dependencies:
|
|
87
77
|
type: :development
|
88
78
|
prerelease: false
|
89
79
|
version_requirements: !ruby/object:Gem::Requirement
|
90
|
-
none: false
|
91
80
|
requirements:
|
92
81
|
- - ! '>='
|
93
82
|
- !ruby/object:Gem::Version
|
@@ -95,7 +84,6 @@ dependencies:
|
|
95
84
|
- !ruby/object:Gem::Dependency
|
96
85
|
name: mongoid
|
97
86
|
requirement: !ruby/object:Gem::Requirement
|
98
|
-
none: false
|
99
87
|
requirements:
|
100
88
|
- - ~>
|
101
89
|
- !ruby/object:Gem::Version
|
@@ -103,7 +91,6 @@ dependencies:
|
|
103
91
|
type: :development
|
104
92
|
prerelease: false
|
105
93
|
version_requirements: !ruby/object:Gem::Requirement
|
106
|
-
none: false
|
107
94
|
requirements:
|
108
95
|
- - ~>
|
109
96
|
- !ruby/object:Gem::Version
|
@@ -111,7 +98,6 @@ dependencies:
|
|
111
98
|
- !ruby/object:Gem::Dependency
|
112
99
|
name: bson_ext
|
113
100
|
requirement: !ruby/object:Gem::Requirement
|
114
|
-
none: false
|
115
101
|
requirements:
|
116
102
|
- - ! '>='
|
117
103
|
- !ruby/object:Gem::Version
|
@@ -119,7 +105,6 @@ dependencies:
|
|
119
105
|
type: :development
|
120
106
|
prerelease: false
|
121
107
|
version_requirements: !ruby/object:Gem::Requirement
|
122
|
-
none: false
|
123
108
|
requirements:
|
124
109
|
- - ! '>='
|
125
110
|
- !ruby/object:Gem::Version
|
@@ -158,27 +143,26 @@ files:
|
|
158
143
|
homepage: https://github.com/wvanbergen/state_machine-audit_trail
|
159
144
|
licenses:
|
160
145
|
- MIT
|
146
|
+
metadata: {}
|
161
147
|
post_install_message:
|
162
148
|
rdoc_options: []
|
163
149
|
require_paths:
|
164
150
|
- lib
|
165
151
|
required_ruby_version: !ruby/object:Gem::Requirement
|
166
|
-
none: false
|
167
152
|
requirements:
|
168
153
|
- - ! '>='
|
169
154
|
- !ruby/object:Gem::Version
|
170
155
|
version: '0'
|
171
156
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
172
|
-
none: false
|
173
157
|
requirements:
|
174
158
|
- - ! '>='
|
175
159
|
- !ruby/object:Gem::Version
|
176
160
|
version: '0'
|
177
161
|
requirements: []
|
178
162
|
rubyforge_project: state_machine
|
179
|
-
rubygems_version:
|
163
|
+
rubygems_version: 2.0.7
|
180
164
|
signing_key:
|
181
|
-
specification_version:
|
165
|
+
specification_version: 4
|
182
166
|
summary: Log transitions on a state machine to support auditing and business process
|
183
167
|
analytics.
|
184
168
|
test_files:
|
@@ -188,3 +172,4 @@ test_files:
|
|
188
172
|
- spec/state_machine/active_record_spec.rb
|
189
173
|
- spec/state_machine/audit_trail_spec.rb
|
190
174
|
- spec/state_machine/mongoid_spec.rb
|
175
|
+
has_rdoc:
|