can_has_state 0.8.0 → 1.0.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 +4 -4
- data/{MIT-LICENSE → LICENSE.txt} +1 -1
- data/lib/can_has_state/machine.rb +7 -11
- data/lib/can_has_state/version.rb +1 -1
- data/test/can_has_state_test.rb +68 -0
- metadata +8 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c5f5601e8f5a886f204c95bfab44e0f2331d48d1ddf1593915518a4506176731
|
4
|
+
data.tar.gz: 7dfb7c2a3f9601bbe495010f116051ebd5731f5425725204e1ff4c5aa7e3413b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aa57e7f886fd54770f5b1031ff139346b616d7cc9445752fa20638c98b00530457f182973535710cf4db5effdebfd5bc4fb516fce195c7f84d0cca2ab8955b1a
|
7
|
+
data.tar.gz: 41adfafeecb3729facfa0f5a293219ca524382d2245af981674045d1a62a83482b78e371b0df89ff01fabeecb14a1c3a9c82337919d07aa9be1e6f7ea7feaeee
|
data/{MIT-LICENSE → LICENSE.txt}
RENAMED
@@ -92,11 +92,7 @@ module CanHasState
|
|
92
92
|
# copy that won't be reset.
|
93
93
|
|
94
94
|
state_machines.each do |column, sm|
|
95
|
-
|
96
|
-
from, to = send("#{column}_before_last_save"), send(column)
|
97
|
-
else
|
98
|
-
from, to = send("#{column}_was"), send(column)
|
99
|
-
end
|
95
|
+
from, to = send("#{column}_before_last_save"), send(column)
|
100
96
|
next if from == to
|
101
97
|
|
102
98
|
tg[column] ||= []
|
@@ -111,23 +107,23 @@ module CanHasState
|
|
111
107
|
end
|
112
108
|
end
|
113
109
|
|
114
|
-
def can_has_state_errors
|
115
|
-
|
110
|
+
def can_has_state_errors(reset: true)
|
111
|
+
@can_has_state_errors = {} if reset || !@can_has_state_errors
|
116
112
|
state_machines.each do |column, sm|
|
117
113
|
from, to = send("#{column}_was"), send(column)
|
118
114
|
if !sm.known?(to)
|
119
|
-
|
115
|
+
@can_has_state_errors[column] = [:invalid_state]
|
120
116
|
elsif from == to
|
121
117
|
next
|
122
118
|
elsif !sm.allow?(self, to) #state_machine_allow?(column, to)
|
123
|
-
|
119
|
+
@can_has_state_errors[column] = [sm.message(to), {from: "'#{from}'", to: "'#{to}'"}]
|
124
120
|
end
|
125
121
|
end
|
126
|
-
|
122
|
+
@can_has_state_errors
|
127
123
|
end
|
128
124
|
|
129
125
|
def validate_state_machines
|
130
|
-
can_has_state_errors.each do |column, (msg, opts)|
|
126
|
+
can_has_state_errors(reset: false).each do |column, (msg, opts)|
|
131
127
|
errors.add column, msg, **(opts||{})
|
132
128
|
end
|
133
129
|
end
|
data/test/can_has_state_test.rb
CHANGED
@@ -406,6 +406,74 @@ class CanHasStateTest < Minitest::Test
|
|
406
406
|
end
|
407
407
|
|
408
408
|
|
409
|
+
def test_errors_resolved_in_later_callback_are_kept
|
410
|
+
# Triggers are skipped when the state_machine has validation errors.
|
411
|
+
# Whether or not to skip is decided in an early before_validation callback.
|
412
|
+
# Even if a later callback resolves the validation error, it's important to
|
413
|
+
# still bubble up the errors since triggers did not run.
|
414
|
+
kl = build_from_skeleton do
|
415
|
+
attr_accessor :have_beans, :coffee_in_hand
|
416
|
+
extend_state_machine :state do
|
417
|
+
state :incredible,
|
418
|
+
require: proc{ coffee_in_hand > 0 }
|
419
|
+
end
|
420
|
+
before_validation { self.coffee_in_hand += 1 if have_beans }
|
421
|
+
def initialize
|
422
|
+
@coffee_in_hand = 0
|
423
|
+
end
|
424
|
+
end
|
425
|
+
m = kl.new
|
426
|
+
m.state = 'incredible'
|
427
|
+
refute m.valid?
|
428
|
+
assert m.errors.of_kind?(:state, :invalid_transition)
|
429
|
+
assert_equal 0, m.coffee_in_hand
|
430
|
+
|
431
|
+
m = kl.new
|
432
|
+
m.have_beans = true
|
433
|
+
m.state = 'incredible'
|
434
|
+
refute m.valid?
|
435
|
+
assert m.errors.of_kind?(:state, :invalid_transition)
|
436
|
+
assert_equal 1, m.coffee_in_hand
|
437
|
+
end
|
438
|
+
|
439
|
+
def test_rerunning_triggers_clears_pre_callback_errors
|
440
|
+
# To resolve the issue above, it is possible to re-eval the state_machine
|
441
|
+
# and run triggers if validations now pass. This is highly discouraged as
|
442
|
+
# complex callback callback interactions like this should be refactored out
|
443
|
+
# if at all possible.
|
444
|
+
# Not an officially supported solution and subject to change, but
|
445
|
+
# documented here to show that it is (presently) possible.
|
446
|
+
kl = build_from_skeleton do
|
447
|
+
attr_accessor :have_beans, :coffee_in_hand, :we_are_incredible
|
448
|
+
extend_state_machine :state do
|
449
|
+
state :incredible,
|
450
|
+
require: proc{ coffee_in_hand > 0 },
|
451
|
+
on_enter: proc{ self.we_are_incredible = true }
|
452
|
+
end
|
453
|
+
before_validation do
|
454
|
+
self.coffee_in_hand += 1 if have_beans
|
455
|
+
run_state_triggers
|
456
|
+
end
|
457
|
+
def initialize
|
458
|
+
@coffee_in_hand = 0
|
459
|
+
end
|
460
|
+
end
|
461
|
+
m = kl.new
|
462
|
+
m.state = 'incredible'
|
463
|
+
refute m.valid?
|
464
|
+
assert m.errors.of_kind?(:state, :invalid_transition)
|
465
|
+
assert_equal 0, m.coffee_in_hand
|
466
|
+
refute m.we_are_incredible
|
467
|
+
|
468
|
+
m = kl.new
|
469
|
+
m.have_beans = true
|
470
|
+
m.state = 'incredible'
|
471
|
+
assert m.valid?
|
472
|
+
assert_equal 1, m.coffee_in_hand
|
473
|
+
assert m.we_are_incredible
|
474
|
+
end
|
475
|
+
|
476
|
+
|
409
477
|
|
410
478
|
def build_from_skeleton(&block)
|
411
479
|
Class.new(Skeleton).tap do |kl|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: can_has_state
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- thomas morgan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-10-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -16,20 +16,20 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '7.0'
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: '
|
22
|
+
version: '8.1'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
27
|
- - ">="
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: '
|
29
|
+
version: '7.0'
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: '
|
32
|
+
version: '8.1'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: minitest
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -81,7 +81,7 @@ executables: []
|
|
81
81
|
extensions: []
|
82
82
|
extra_rdoc_files: []
|
83
83
|
files:
|
84
|
-
-
|
84
|
+
- LICENSE.txt
|
85
85
|
- README.md
|
86
86
|
- Rakefile
|
87
87
|
- lib/can_has_state.rb
|
@@ -116,7 +116,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
116
116
|
- !ruby/object:Gem::Version
|
117
117
|
version: '0'
|
118
118
|
requirements: []
|
119
|
-
rubygems_version: 3.
|
119
|
+
rubygems_version: 3.5.11
|
120
120
|
signing_key:
|
121
121
|
specification_version: 4
|
122
122
|
summary: Super simple state machine for ActiveModel
|