soft_validator 1.0.0 → 1.0.1

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: 64db8fb56e161e44e7a584528a2c8dd5831ce1c6e10f77d0a02305ff51ae2aea
4
- data.tar.gz: 403ef75272880d067ab2657ae678bee52b7f9ff3d1297230e1ed8ae5b7025227
3
+ metadata.gz: 2914d0f077469311e25bce9c99d506c2f61ae2d298f5b4b16822186ca91566df
4
+ data.tar.gz: bce8ec1c4fedbc091b355821b270b11ac1d93affd25350a9cc316e5933a65dba
5
5
  SHA512:
6
- metadata.gz: 7e62f0f978d8850a29119294f1a56cc6b52d0114c093644f7d61cb893feb5998e1ff9916d90c58be37bd6e9b5105e58943adee8b8ae8836fda06c8350864d68b
7
- data.tar.gz: 9bcbfe1be63d91adad556557b50cb6dfa2babe13b851df51f3cd0fd1869cd14652dbc36d3945a1c004d6df14388a14412ddfe7e39e1bc189db7603f10292495a
6
+ metadata.gz: 543464c8e692cb122d2ba14674336c5947577ec65fd40a3da9cfea289e65d0eb8081b5101d209231b514e4c1ac339ff79d17a38e1271bd00302dc194b95e3c0d
7
+ data.tar.gz: baca486b0040cc4a5d281a81cfc42a0e8bb278fe5ef7191543957b05bd28c7b90b5b13370c35530f7f2005b3966db67798ce4d756592f1bc2bbd93168f0ffb97
data/CHANGELOG.md CHANGED
@@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## 1.0.1
8
+
9
+ ### Fixed
10
+
11
+ - Soft validation errors are now removed by object identity instead of by matching attribute, type, and options. Previously a soft validation could delete errors added by hard validations of the same type on the same attribute, and a soft error identical to an existing hard error would be left on the record as a duplicate.
12
+ - Setting `enforced: false` on a soft validation now overrides the global `SoftValidator.enforced` setting.
13
+ - The `:allow_nil`, `:allow_blank`, `:strict`, and `:prepend` options can now be used on a soft validation without raising an unknown validator error.
14
+ - Wrapped validators with falsy options (e.g. `soft: {presence: false}`) are now skipped, matching the behavior of `validates`.
15
+ - The `:enforced` option is now evaluated once per attribute validation instead of once per wrapped validator, so a `Proc` value (e.g. a feature flag) cannot produce inconsistent enforcement within a single validation pass.
16
+
7
17
  ## 1.0.0
8
18
 
9
19
  ### Added
data/README.md CHANGED
@@ -1,7 +1,6 @@
1
1
  # SoftValidator
2
2
 
3
3
  [![Continuous Integration](https://github.com/bdurand/soft_validator/actions/workflows/continuous_integration.yml/badge.svg)](https://github.com/bdurand/soft_validator/actions/workflows/continuous_integration.yml)
4
- [![Regression Test](https://github.com/bdurand/soft_validator/actions/workflows/regression_test.yml/badge.svg)](https://github.com/bdurand/soft_validator/actions/workflows/regression_test.yml)
5
4
  [![Ruby Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://github.com/testdouble/standard)
6
5
  [![Gem Version](https://badge.fury.io/rb/soft_validator.svg)](https://badge.fury.io/rb/soft_validator)
7
6
 
@@ -21,21 +20,21 @@ Each of the validations in the `:soft` validation will still be run when the rec
21
20
 
22
21
  ### Notifications
23
22
 
24
- Soft validation errors are published via ActiveSupport notifications. You can handle errors generted from soft validations by subscribing to the `validation_error.soft_validator` event. For instance, you could log the errors to the Rails logger by adding this code to an initializer:
23
+ Soft validation errors are published via ActiveSupport notifications. You can handle errors generated from soft validations by subscribing to the `validation_error.soft_validator` event. For instance, you could log the errors to the Rails logger by adding this code to an initializer:
25
24
 
26
25
  ```ruby
27
26
  ActiveSupport::Notifications.subscribe("validation_error.soft_validator") do |event|
28
27
  error = event.payload[:error]
29
- message = "Soft validation error on {error.base.class.name}(#{error.base.id}): #{error.full_message}"
28
+ message = "Soft validation error on #{error.base.class.name}(#{error.base.id}): #{error.full_message}"
30
29
  Rails.logger.warn(message)
31
30
  end
32
31
  ```
33
32
 
34
- You can also the `SoftValidator.subscribe` helper method to set up subscriptions. This code will do the same thing as the code above:
33
+ You can also use the `SoftValidator.subscribe` helper method to set up subscriptions. This code will do the same thing as the code above:
35
34
 
36
35
  ```ruby
37
36
  SoftValidator.subscribe do |error|
38
- message = "Soft validation error on {error.base.class.name}(#{error.base.id}): #{error.full_message}"
37
+ message = "Soft validation error on #{error.base.class.name}(#{error.base.id}): #{error.full_message}"
39
38
  Rails.logger.warn(message)
40
39
  end
41
40
  ```
@@ -50,7 +49,7 @@ You can disable the log subscriber by calling `SoftValidator::LogSubscriber.deta
50
49
 
51
50
  ### Enforcing with feature flags
52
51
 
53
- You can turn a soft validation into a hard validation by setting the `:enforce` option to `true`. This will cause the validation to generate errors as normal. You can use this option to enable validation with a feature flag.
52
+ You can turn a soft validation into a hard validation by setting the `:enforced` option to `true`. This will cause the validation to generate errors as normal. You can also set the option to a `Proc` that will be evaluated each time the validation is run, which lets you enable the validation with a feature flag.
54
53
 
55
54
  ```ruby
56
55
  class Thing < ApplicationRecord
@@ -58,16 +57,16 @@ class Thing < ApplicationRecord
58
57
  presence: true,
59
58
  soft: {
60
59
  inclusion: {in: ["feet", "meters"]},
61
- enforce: ENV.fetch("ENFORCE_UNITS", !Rails.env.production?.to_s) == "true"
60
+ enforced: -> { ENV["ENFORCE_UNITS"] == "true" }
62
61
  }
63
62
  end
64
63
  ```
65
64
 
66
- The global default for enforcing soft validations can be changed by setting `SoftValidator.enforce`. If it is set to `true`, soft validations will be enforced by default. In Rails applications this is set automatically in the development and test environments since you would typically want to see the errors in those environments so that you can fix them.
65
+ The global default for enforcing soft validations can be changed by setting `SoftValidator.enforced = true`. If it is set to `true`, soft validations will be enforced by default. In Rails applications this is set automatically in the development and test environments since you would typically want to see the errors in those environments so that you can fix them. You can opt a validation out of the global default by explicitly setting `enforced: false` on that validation.
67
66
 
68
67
  ### Conditional options
69
68
 
70
- If you want to add any of the standard conditional options for the validator (i.e. `:if`, `:unless`, `:on`, `:prepend`), you need to add it to the soft validator and not the wrapped validator.
69
+ If you want to add any of the standard conditional options for the validator (i.e. `:if`, `:unless`, `:on`, `:allow_nil`, `:allow_blank`, `:prepend`), you need to add it to the soft validator and not the wrapped validator.
71
70
 
72
71
  ```ruby
73
72
  class Thing < ApplicationRecord
@@ -95,7 +94,7 @@ $ bundle
95
94
 
96
95
  Or install it yourself as:
97
96
  ```bash
98
- $ gem install gem "soft_validator"
97
+ $ gem install soft_validator
99
98
  ```
100
99
 
101
100
  ## Contributing
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.0
1
+ 1.0.1
@@ -9,7 +9,7 @@ class SoftValidator < ActiveModel::EachValidator
9
9
 
10
10
  class << self
11
11
  def enforced?
12
- @enforced ||= false
12
+ !!@enforced
13
13
  end
14
14
 
15
15
  attr_writer :enforced
@@ -27,28 +27,37 @@ class SoftValidator < ActiveModel::EachValidator
27
27
  end
28
28
 
29
29
  def validate_each(record, attribute, value)
30
- existing_errors = record.errors.errors.dup
30
+ enforced = enforced?
31
31
  @validators.each do |validator|
32
+ existing_errors = record.errors.errors.dup
32
33
  validator.validate_each(record, attribute, value)
33
- next if enforced?
34
+ next if enforced
34
35
 
35
- (record.errors.errors - existing_errors).each do |error|
36
- record.errors.delete(error.attribute, error.type, **error.options)
36
+ new_errors = record.errors.errors.reject { |error| existing_errors.any? { |existing| existing.equal?(error) } }
37
+ new_errors.each do |error|
38
+ record.errors.errors.delete_if { |e| e.equal?(error) }
37
39
  ActiveSupport::Notifications.instrument(ERROR_EVENT, error: error)
38
40
  end
39
41
  end
40
42
  end
41
43
 
42
44
  def enforced?
43
- enforced = options[:enforced]
44
- enforced = enforced.call if enforced.is_a?(Proc)
45
- enforced || self.class.enforced?
45
+ if options.key?(:enforced)
46
+ enforced = options[:enforced]
47
+ enforced = enforced.call if enforced.is_a?(Proc)
48
+ !!enforced
49
+ else
50
+ self.class.enforced?
51
+ end
46
52
  end
47
53
 
48
54
  private
49
55
 
50
56
  def wrapped_validators(klass)
51
- options.except(:enforced, :if, :unless, :on).map do |validator_name, validator_options|
57
+ validator_options_list = options.except(:enforced, :if, :unless, :on, :allow_nil, :allow_blank, :strict, :prepend)
58
+ validator_options_list.filter_map do |validator_name, validator_options|
59
+ next unless validator_options
60
+
52
61
  class_name = "#{validator_name.to_s.camelize}Validator"
53
62
 
54
63
  begin
@@ -8,6 +8,12 @@ Gem::Specification.new do |spec|
8
8
  spec.homepage = "https://github.com/bdurand/soft_validator"
9
9
  spec.license = "MIT"
10
10
 
11
+ spec.metadata = {
12
+ "homepage_uri" => spec.homepage,
13
+ "source_code_uri" => spec.homepage,
14
+ "changelog_uri" => "#{spec.homepage}/blob/main/CHANGELOG.md"
15
+ }
16
+
11
17
  # Specify which files should be added to the gem when it is released.
12
18
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
13
19
  ignore_files = %w[
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: soft_validator
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Durand
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-03-29 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: activemodel
@@ -38,7 +37,6 @@ dependencies:
38
37
  - - ">="
39
38
  - !ruby/object:Gem::Version
40
39
  version: '0'
41
- description:
42
40
  email:
43
41
  - bbdurand@gmail.com
44
42
  executables: []
@@ -56,8 +54,10 @@ files:
56
54
  homepage: https://github.com/bdurand/soft_validator
57
55
  licenses:
58
56
  - MIT
59
- metadata: {}
60
- post_install_message:
57
+ metadata:
58
+ homepage_uri: https://github.com/bdurand/soft_validator
59
+ source_code_uri: https://github.com/bdurand/soft_validator
60
+ changelog_uri: https://github.com/bdurand/soft_validator/blob/main/CHANGELOG.md
61
61
  rdoc_options: []
62
62
  require_paths:
63
63
  - lib
@@ -72,8 +72,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
72
72
  - !ruby/object:Gem::Version
73
73
  version: '0'
74
74
  requirements: []
75
- rubygems_version: 3.4.10
76
- signing_key:
75
+ rubygems_version: 4.0.3
77
76
  specification_version: 4
78
77
  summary: ActiveModel/ActiveRecord validator that can wrap other validators to notify
79
78
  of errors so that new validations can be safely added to an existing model.