sequel-state-machine 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1eb11cc183e1cfcfc7917f505b02b0f801888492fcf73ac6538e5915972cc799
4
- data.tar.gz: 355f305b70481b88cd306aed45e4bd6ec8b8706ecd921f17fb18e872e85ea36c
3
+ metadata.gz: 32bf94c0e52e6d2fcaf7593f02f4834f689ee462a378dfc7d561e3e29db79258
4
+ data.tar.gz: a99a5e2ccd052cecd228ccc7c702bde70b675b86afac2fbf2b69d95432a9b8b5
5
5
  SHA512:
6
- metadata.gz: e26ed08fbc26ece33859b8b68b1ce95573060437054ed1c2e7f69e751c80c5a9d0e29c0ad81ab2c2ec1985c54bcc0fd8327d940329868e7c0937b1baa0f4f64f
7
- data.tar.gz: 32164513eb750973c18e54b73defeb9aa3e45635653725733ff4c1f0f1665693a2eecb569b2d749d04010c586c86bf44f20b8558e6c44f5df85ce9c73b47c8de
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.status,
76
- to_state: self.status,
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
- current_state = self.send(self._state_value_attr).to_sym
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
- return true if state_req[:from]&.matches?(current_state)
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[self._state_value_attr]
177
+ state = self.state_machine_status
134
178
  return if states.include?(state)
135
- self.errors.add(self._state_value_attr, "status '#{state}' must be one of (#{states.sort.join(', ')})")
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.status
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.status
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.status}"
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.status}"
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(
@@ -2,6 +2,6 @@
2
2
 
3
3
  module StateMachines
4
4
  module Sequel
5
- VERSION = "1.0.1"
5
+ VERSION = "1.1.0"
6
6
  end
7
7
  end
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.1
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-03-23 00:00:00.000000000 Z
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.