can_has_state 0.8.0 → 1.0.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: 0b2d2008ba870961e06cebe22f027b133b46c5f078315938c9338edfd99678f5
4
- data.tar.gz: 2d4e7dbfd0bb896e01dfdaf66933b3b483f71915579f5d66d42fde1cbd0416de
3
+ metadata.gz: c5f5601e8f5a886f204c95bfab44e0f2331d48d1ddf1593915518a4506176731
4
+ data.tar.gz: 7dfb7c2a3f9601bbe495010f116051ebd5731f5425725204e1ff4c5aa7e3413b
5
5
  SHA512:
6
- metadata.gz: 9e18bb675dd1acc0b84bb8539f67ca9c483f7ff618927b9baef5cdc738ba7a723cac0cccbaed68dfd0291925a2af5a8cda4ebf22b250ead0d39d813e389ecd86
7
- data.tar.gz: 2cc03d656532de9061758242d7daaab074f979665323a071d432b1c220e050951da7750ca6f38c5ef1c8e1e4633f76ce16bd8f404fbe9e5e31ba8fe0a6426f17
6
+ metadata.gz: aa57e7f886fd54770f5b1031ff139346b616d7cc9445752fa20638c98b00530457f182973535710cf4db5effdebfd5bc4fb516fce195c7f84d0cca2ab8955b1a
7
+ data.tar.gz: 41adfafeecb3729facfa0f5a293219ca524382d2245af981674045d1a62a83482b78e371b0df89ff01fabeecb14a1c3a9c82337919d07aa9be1e6f7ea7feaeee
@@ -1,4 +1,4 @@
1
- Copyright 2012-2023 thomas morgan
1
+ Copyright 2012-2024 thomas morgan
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
@@ -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
- if respond_to?("#{column}_before_last_save") # rails 5.1+
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
- err = {}
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
- err[column] = [:invalid_state]
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
- err[column] = [sm.message(to), {from: "'#{from}'", to: "'#{to}'"}]
119
+ @can_has_state_errors[column] = [sm.message(to), {from: "'#{from}'", to: "'#{to}'"}]
124
120
  end
125
121
  end
126
- err
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
@@ -1,3 +1,3 @@
1
1
  module CanHasState
2
- VERSION = '0.8.0'
2
+ VERSION = '1.0.0'
3
3
  end
@@ -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.8.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: 2023-01-25 00:00:00.000000000 Z
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: '6.0'
19
+ version: '7.0'
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: '7.2'
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: '6.0'
29
+ version: '7.0'
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: '7.2'
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
- - MIT-LICENSE
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.3.26
119
+ rubygems_version: 3.5.11
120
120
  signing_key:
121
121
  specification_version: 4
122
122
  summary: Super simple state machine for ActiveModel