can_has_state 0.8.0 → 0.9.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/lib/can_has_state/machine.rb +6 -6
- data/lib/can_has_state/version.rb +1 -1
- data/test/can_has_state_test.rb +68 -0
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 516a5676e62907d7868c5a0812c760e292b87c8c785cb246c5eb3bd2db2d7a41
|
4
|
+
data.tar.gz: 1e4b230a4a4c933b1db2884b2f7490439c9fb2f4f18b1ee686286decc2640903
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cb9ef6c65385ef382a01d9f73c40da6217136f9939fea20eb6aae0183ce57f492e119302fc560f9273b2f6c2933cde3fa2c50daf3e0f13d038cf19dbfa377d5b
|
7
|
+
data.tar.gz: f1aee70c43b00b6ae153c63583db1d1bf4bd9adb072fa4b5adf33eecd1b4f3c1668aa1aba54438b296158ad858475a1d52333ce95f0e2e9959d1d1fb8b7d499b
|
@@ -111,23 +111,23 @@ module CanHasState
|
|
111
111
|
end
|
112
112
|
end
|
113
113
|
|
114
|
-
def can_has_state_errors
|
115
|
-
|
114
|
+
def can_has_state_errors(reset: true)
|
115
|
+
@can_has_state_errors = {} if reset || !@can_has_state_errors
|
116
116
|
state_machines.each do |column, sm|
|
117
117
|
from, to = send("#{column}_was"), send(column)
|
118
118
|
if !sm.known?(to)
|
119
|
-
|
119
|
+
@can_has_state_errors[column] = [:invalid_state]
|
120
120
|
elsif from == to
|
121
121
|
next
|
122
122
|
elsif !sm.allow?(self, to) #state_machine_allow?(column, to)
|
123
|
-
|
123
|
+
@can_has_state_errors[column] = [sm.message(to), {from: "'#{from}'", to: "'#{to}'"}]
|
124
124
|
end
|
125
125
|
end
|
126
|
-
|
126
|
+
@can_has_state_errors
|
127
127
|
end
|
128
128
|
|
129
129
|
def validate_state_machines
|
130
|
-
can_has_state_errors.each do |column, (msg, opts)|
|
130
|
+
can_has_state_errors(reset: false).each do |column, (msg, opts)|
|
131
131
|
errors.add column, msg, **(opts||{})
|
132
132
|
end
|
133
133
|
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|
|