sequel-state-machine 1.0.1 → 1.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.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 32bf94c0e52e6d2fcaf7593f02f4834f689ee462a378dfc7d561e3e29db79258
|
4
|
+
data.tar.gz: a99a5e2ccd052cecd228ccc7c702bde70b675b86afac2fbf2b69d95432a9b8b5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 10d259cf6ff25cdabe78ef6699ff6fa9be62de332cd9c45901b5295be687159cbf10e7738426ab94c0f2f4f2c0af3cccf44d3ba371c026f30e00bb6677910747
|
7
|
+
data.tar.gz: 349b9378af67e386b705d9d1d6e26ca2a48ff953b322f1a47dc40da308ab240e289d1042b53acbaaf2525df408a9c05be5fd62c33b4986b28452a4d51351ced5
|
@@ -7,7 +7,53 @@ require "state_machines/sequel"
|
|
7
7
|
module Sequel
|
8
8
|
module Plugins
|
9
9
|
module StateMachine
|
10
|
+
class InvalidConfiguration < RuntimeError; end
|
11
|
+
|
12
|
+
def self.apply(_model, _opts={})
|
13
|
+
nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.configure(model, opts={})
|
17
|
+
col = opts.is_a?(Symbol) ? opts : nil
|
18
|
+
model.instance_eval do
|
19
|
+
# See state_machine_status_column.
|
20
|
+
# We must defer defaulting the value in case the plugin
|
21
|
+
# comes ahead of the state machine (we can see a valid state machine,
|
22
|
+
# but the attribute/name will always be :state, due to some configuration
|
23
|
+
# order of operations).
|
24
|
+
@sequel_state_machine_status_column = col if col
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
10
28
|
module InstanceMethods
|
29
|
+
private def state_machine_status_column
|
30
|
+
col = self.class.instance_variable_get(:@sequel_state_machine_status_column)
|
31
|
+
return col unless col.nil?
|
32
|
+
if self.respond_to?(:_state_value_attr)
|
33
|
+
self.class.instance_variable_set(:@sequel_state_machine_status_column, self._state_value_attr)
|
34
|
+
return self._state_value_attr
|
35
|
+
end
|
36
|
+
if !self.class.respond_to?(:state_machines) || self.class.state_machines.empty?
|
37
|
+
msg = "Model must extend StateMachines::MacroMethods and have one state_machine."
|
38
|
+
raise InvalidConfiguration, msg
|
39
|
+
end
|
40
|
+
if self.class.state_machines.length > 1
|
41
|
+
msg = "Cannot use sequel-state-machine with multiple state machines. " \
|
42
|
+
"Please file an issue at https://github.com/lithictech/sequel-state-machine/issues " \
|
43
|
+
"if you need this capability."
|
44
|
+
raise InvalidConfiguration, msg
|
45
|
+
end
|
46
|
+
self.class.instance_variable_set(:@sequel_state_machine_status_column, self.class.state_machine.attribute)
|
47
|
+
end
|
48
|
+
|
49
|
+
private def state_machine_status
|
50
|
+
return self.send(self.state_machine_status_column)
|
51
|
+
end
|
52
|
+
|
53
|
+
def sequel_state_machine_status
|
54
|
+
return state_machine_status
|
55
|
+
end
|
56
|
+
|
11
57
|
def new_audit_log
|
12
58
|
audit_log_assoc = self.class.association_reflections[:audit_logs]
|
13
59
|
model = Kernel.const_get(audit_log_assoc[:class_name])
|
@@ -72,8 +118,8 @@ module Sequel
|
|
72
118
|
audlog.set(
|
73
119
|
at: Time.now,
|
74
120
|
event: event,
|
75
|
-
from_state: self.
|
76
|
-
to_state: self.
|
121
|
+
from_state: self.state_machine_status,
|
122
|
+
to_state: self.state_machine_status,
|
77
123
|
messages: audlog.class.state_machine_messages_supports_array ? messages : messages.join("\n"),
|
78
124
|
reason: reason || "",
|
79
125
|
actor: StateMachines::Sequel.current_actor,
|
@@ -114,25 +160,24 @@ module Sequel
|
|
114
160
|
|
115
161
|
# Return true if the given event can be transitioned into by the current state.
|
116
162
|
def valid_state_path_through?(event)
|
117
|
-
|
163
|
+
current_state_str = self.state_machine_status.to_s
|
164
|
+
current_state_sym = current_state_str.to_sym
|
118
165
|
event_obj = self.class.state_machine.events[event] or raise "Invalid event #{event}"
|
119
166
|
event_obj.branches.each do |branch|
|
120
167
|
branch.state_requirements.each do |state_req|
|
121
|
-
|
168
|
+
next unless (from = state_req[:from])
|
169
|
+
return true if from.matches?(current_state_str) || from.matches?(current_state_sym)
|
122
170
|
end
|
123
171
|
end
|
124
172
|
return false
|
125
173
|
end
|
126
174
|
|
127
|
-
def _state_value_attr
|
128
|
-
return @_state_value_attr ||= self.class.state_machine.attribute
|
129
|
-
end
|
130
|
-
|
131
175
|
def validates_state_machine
|
132
176
|
states = self.class.state_machine.states.map(&:value)
|
133
|
-
state = self
|
177
|
+
state = self.state_machine_status
|
134
178
|
return if states.include?(state)
|
135
|
-
self.errors.add(self.
|
179
|
+
self.errors.add(self.state_machine_status_column,
|
180
|
+
"state '#{state}' must be one of (#{states.sort.join(', ')})",)
|
136
181
|
end
|
137
182
|
end
|
138
183
|
|
@@ -36,14 +36,14 @@ module Sequel
|
|
36
36
|
|
37
37
|
module DatasetMethods
|
38
38
|
def failed
|
39
|
-
colmap = self.state_machine_column_mappings
|
39
|
+
colmap = self.model.state_machine_column_mappings
|
40
40
|
tostate_col = colmap[:to_state]
|
41
41
|
fromstate_col = colmap[:from_state]
|
42
42
|
return self.where(tostate_col => fromstate_col)
|
43
43
|
end
|
44
44
|
|
45
45
|
def succeeded
|
46
|
-
colmap = self.state_machine_column_mappings
|
46
|
+
colmap = self.model.state_machine_column_mappings
|
47
47
|
tostate_col = colmap[:to_state]
|
48
48
|
fromstate_col = colmap[:from_state]
|
49
49
|
return self.exclude(tostate_col => fromstate_col)
|
@@ -6,7 +6,7 @@ RSpec::Matchers.define :transition_on do |event|
|
|
6
6
|
match do |receiver|
|
7
7
|
raise 'must provide a "to" state' if (@to || "").to_s.empty?
|
8
8
|
receiver.send(event, *@args)
|
9
|
-
@to == receiver.
|
9
|
+
@to == receiver.send(:state_machine_status)
|
10
10
|
end
|
11
11
|
|
12
12
|
chain :to do |to_state|
|
@@ -23,10 +23,10 @@ RSpec::Matchers.define :transition_on do |event|
|
|
23
23
|
|
24
24
|
failure_message do |receiver|
|
25
25
|
msg =
|
26
|
-
if @to == receiver.
|
26
|
+
if @to == receiver.state_machine_status
|
27
27
|
"expected that event #{event} would transition, but did not"
|
28
28
|
else
|
29
|
-
"expected that event #{event} would transition to #{@to} but is #{receiver.
|
29
|
+
"expected that event #{event} would transition to #{@to} but is #{receiver.state_machine_status}"
|
30
30
|
end
|
31
31
|
(msg += "\n#{receiver.audit_logs.map(&:inspect).join("\n")}") if @audit
|
32
32
|
msg
|
@@ -43,11 +43,12 @@ RSpec::Matchers.define :not_transition_on do |event|
|
|
43
43
|
end
|
44
44
|
|
45
45
|
failure_message do |receiver|
|
46
|
-
"expected that event #{event} would not transition, but did and is now #{receiver.
|
46
|
+
"expected that event #{event} would not transition, but did and is now #{receiver.state_machine_status}"
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
50
|
RSpec.shared_examples "a state machine with audit logging" do |event, to_state|
|
51
|
+
let(:machine) { raise NotImplementedError, "must override let(:machine)" }
|
51
52
|
it "logs transitions" do
|
52
53
|
expect(machine).to transition_on(event).to(to_state)
|
53
54
|
expect(machine.audit_logs).to contain_exactly(
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sequel-state-machine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lithic Tech
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-04-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -94,6 +94,20 @@ dependencies:
|
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '5.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: simplecov
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
112
|
name: sqlite3
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -122,6 +136,20 @@ dependencies:
|
|
122
136
|
- - "~>"
|
123
137
|
- !ruby/object:Gem::Version
|
124
138
|
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: timecop
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
125
153
|
description: |
|
126
154
|
sequel-state-machine hooks together the excellent Ruby Sequel ORM to
|
127
155
|
the state-machines library, with auditing and other tools.
|