parametric 0.2.19 → 0.2.20

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: 98676c8edebba19bd1adff020f5eadf9dce07e44f89125be4f0451d6bdee50cf
4
- data.tar.gz: 5a5d0ecded864e5185d2b1d1cafe5eeb2307d92cf52c4111e7dd85ebe65c0321
3
+ metadata.gz: 0a4f53d13fdfe4476f9467127b58740f86b8f301979b56940eb9e228fd588225
4
+ data.tar.gz: 5b26af44589c43bc2825a75e988318eefc3147581183a4c4cc65af5b98a47fed
5
5
  SHA512:
6
- metadata.gz: 1a3b81c816a02516450bdeb70ddb5b804741481ec0084167f31cdddcef4c3734f25b0d69da022048d9889c7b47a462cd821bf3a4cef07d719aff9b57293e10ef
7
- data.tar.gz: 5a2cd8dd4d68cd896901d744f656fca3385f6d3763bc05d62dbd1b6c53362a32092781e7bd57e439b27c6e0071d1179a0355372778d33b9c96f893e6fd4e07d3
6
+ metadata.gz: a5f7fbdfee4363b05e2044439499bd17954552b6a8c9b95442a613969e4775dcc2d05ee2340ba06df3b55b12df2414a16b672fe76c5b1ee2485ba6dede5cbdf7
7
+ data.tar.gz: 9ea239bd608ef85e8f92a07060e10aff57b0552b92562b4e4ea1507e1a91a71173382565fd7f198d8f3a2595756b8a6badeb46638de14997fd15bf13250e4910
data/README.md CHANGED
@@ -293,6 +293,21 @@ Like `:declared`, it stops the policy chain if a key is not in input, but it als
293
293
  field(:name).policy(:declared_no_default).present
294
294
  ```
295
295
 
296
+ ### :nullable
297
+
298
+ Check that key is present in input. If value is `nil`, processing and validations stop, but key is still included in output.
299
+
300
+ ```ruby
301
+ schema = Parametric::Schema.new do
302
+ field(:age).nullable.type(:integer).policy(:gt: 21)
303
+ end
304
+
305
+ schema.resolve(age: '22').output[:age] # 22
306
+ schema.resolve(age: 10).errors[:age] # has error because < 21
307
+ schema.resolve(age: nil).output[:age] # nil, no errors
308
+ schema.resolve({}).output[:age] # nil, no errors
309
+ ```
310
+
296
311
  ### :gt
297
312
 
298
313
  Validate that the value is greater than a number
@@ -387,6 +402,12 @@ class MyPolicyRunner
387
402
  true
388
403
  end
389
404
 
405
+ # If this policy is not eligible, should the key and value be included in the output?
406
+ # @return [Boolean]
407
+ def include_non_eligible_in_ouput?
408
+ true
409
+ end
410
+
390
411
  # If [false], add [#message] to result errors and halt processing field.
391
412
  # @return [Boolean]
392
413
  def valid?
@@ -88,7 +88,7 @@ module Parametric
88
88
  begin
89
89
  pol = policy.build(key, value, payload:, context:)
90
90
  if !pol.eligible?
91
- eligible = false
91
+ eligible = pol.include_non_eligible_in_ouput?
92
92
  if has_default?
93
93
  eligible = true
94
94
  value = default_block.call(key, payload, context)
@@ -22,5 +22,9 @@ module Parametric
22
22
  def options(opts)
23
23
  policy :options, opts
24
24
  end
25
+
26
+ def nullable
27
+ policy :nullable
28
+ end
25
29
  end
26
30
  end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Parametric
4
+ # A policy that allows a field to be nullable.
5
+ # Fields with nil values are not processed further, and the value is returned as-is.
6
+ # @example
7
+ # field(:age).nullable.type(:integer)
8
+ # field(:age).nullable.type(:integer).required
9
+ #
10
+ class NullablePolicy
11
+ def meta_data; {}; end
12
+
13
+ def build(key, value, payload:, context:)
14
+ Runner.new(key, value, payload, context)
15
+ end
16
+
17
+ class Runner
18
+ def initialize(key, value, payload, context)
19
+ @key = key
20
+ @value = value
21
+ @payload = payload
22
+ @context = context
23
+ end
24
+
25
+ # Should this policy run at all?
26
+ # returning [false] halts the field policy chain.
27
+ # @return [Boolean]
28
+ def eligible?
29
+ @payload.key?(@key) && !@value.nil?
30
+ end
31
+
32
+ # If this policy is not eligible, should the key and value be included in the output?
33
+ # @return [Boolean]
34
+ def include_non_eligible_in_ouput?
35
+ true
36
+ end
37
+
38
+ # If [false], add [#message] to result errors and halt processing field.
39
+ # @return [Boolean]
40
+ def valid?
41
+ true
42
+ end
43
+
44
+ # Coerce the value, or return as-is.
45
+ # @return [Any]
46
+ def value
47
+ @value
48
+ end
49
+
50
+ # Error message for this policy
51
+ # @return [String]
52
+ def message
53
+ ''
54
+ end
55
+ end
56
+ end
57
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'parametric/nullable_policy'
4
+
3
5
  module Parametric
4
6
  module Policies
5
7
  class Format
@@ -59,6 +61,7 @@ module Parametric
59
61
  Parametric.policy :format, Policies::Format
60
62
  Parametric.policy :email, Policies::Format.new(EMAIL_REGEXP, 'invalid email')
61
63
  Parametric.policy :value, Policies::Value
64
+ Parametric.policy :nullable, Parametric::NullablePolicy
62
65
 
63
66
  Parametric.policy :noop do
64
67
  eligible do |value, key, payload|
@@ -14,6 +14,14 @@ module Parametric
14
14
  @policy.eligible?(@raw_value, @key, @payload)
15
15
  end
16
16
 
17
+ # If a policy is not #eligible?, use this to decide if its key
18
+ # should still be included in output hash.
19
+ #
20
+ # @return [Boolean]
21
+ def include_non_eligible_in_ouput?
22
+ false
23
+ end
24
+
17
25
  # @return [Boolean]
18
26
  def valid?
19
27
  @policy.valid?(value, @key, @payload)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Parametric
4
- VERSION = '0.2.19'
4
+ VERSION = '0.2.20'
5
5
  end
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'nullable policy' do
6
+ specify 'dealing with nil values' do
7
+ schema = Parametric::Schema.new do
8
+ field(:age).nullable.type(:integer)
9
+ end
10
+
11
+ expect(schema.resolve({ age: 10 }).output[:age]).to eq 10
12
+ expect(schema.resolve({ age: '10' }).output[:age]).to eq 10
13
+ expect(schema.resolve({ age: nil }).output[:age]).to eq nil
14
+ expect(schema.resolve({ age: false }).output[:age]).to be false
15
+ expect(schema.resolve({ nope: 1 }).output.key?(:age)).to be true
16
+ end
17
+
18
+ specify 'with required/present types' do
19
+ schema = Parametric::Schema.new do
20
+ field(:age).nullable.type(:integer).present.policy(:gt, 9)
21
+ end
22
+
23
+ schema.resolve({ age: '10' }).tap do |r|
24
+ expect(r.output[:age]).to eq 10
25
+ expect(r.errors.any?).to be false
26
+ end
27
+
28
+ schema.resolve({ age: '7' }).tap do |r|
29
+ expect(r.output[:age]).to eq 7
30
+ expect(r.errors.any?).to be true
31
+ end
32
+
33
+ schema.resolve({ age: nil }).tap do |r|
34
+ expect(r.output[:age]).to eq nil
35
+ expect(r.errors.any?).to be false
36
+ end
37
+
38
+ schema.resolve({}).tap do |r|
39
+ expect(r.output.key?(:age)).to be true
40
+ expect(r.output[:age]).to eq nil
41
+ expect(r.errors.any?).to be false
42
+ end
43
+ end
44
+
45
+ specify 'interacting with custom types that validate' do
46
+ Parametric.policy :validating_integer do
47
+ exp = /^\d+$/
48
+
49
+ validate do |value, _key, _context|
50
+ !!(value.to_s =~ exp)
51
+ end
52
+
53
+ coerce do |value, _key, _context|
54
+ if value.to_s =~ exp
55
+ value.to_i
56
+ else
57
+ value
58
+ end
59
+ end
60
+
61
+ message do
62
+ 'error!'
63
+ end
64
+ end
65
+
66
+ schema = Parametric::Schema.new do
67
+ field(:age).nullable.type(:validating_integer)
68
+ end
69
+
70
+ expect(schema.resolve({ age: 10 }).output[:age]).to eq 10
71
+ expect(schema.resolve({ age: '10' }).output[:age]).to eq 10
72
+ schema.resolve({ age: 'nope' }).tap do |r|
73
+ expect(r.output[:age]).to eq 'nope'
74
+ expect(r.errors.any?).to be true
75
+ end
76
+ schema.resolve({ age: nil }).tap do |r|
77
+ expect(r.output.key?(:age)).to be(true)
78
+ expect(r.output[:age]).to eq nil
79
+ expect(r.errors.any?).to be false
80
+ end
81
+ expect(schema.resolve({ age: nil }).output[:age]).to eq nil
82
+ expect(schema.resolve({ nope: 1 }).output.key?(:age)).to be true
83
+ end
84
+
85
+ specify 'interacting with required fields' do
86
+ schema = Parametric::Schema.new do
87
+ field(:age).nullable.type(:integer).required
88
+ end
89
+
90
+ result = schema.resolve({})
91
+ expect(result.output.key?(:age)).to be(true)
92
+ expect(result.output[:age]).to eq nil
93
+ expect(result.errors['$.age']).to eq nil
94
+ end
95
+
96
+ specify 'copying policies via Field#from' do
97
+ source_schema = Parametric::Schema.new do
98
+ field(:age).nullable.type(:integer).required
99
+ end
100
+
101
+ target_schema = Parametric::Schema.new do |sc, _|
102
+ source_schema.fields.each do |key, f|
103
+ sc.field(key).from(f)
104
+ end
105
+ end
106
+
107
+ result = target_schema.resolve({})
108
+ expect(result.output[:age]).to eq nil
109
+ expect(result.errors['$.age']).to eq nil
110
+ end
111
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parametric
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.19
4
+ version: 0.2.20
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ismael Celis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-08-10 00:00:00.000000000 Z
11
+ date: 2023-12-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -76,6 +76,7 @@ files:
76
76
  - lib/parametric/dsl.rb
77
77
  - lib/parametric/field.rb
78
78
  - lib/parametric/field_dsl.rb
79
+ - lib/parametric/nullable_policy.rb
79
80
  - lib/parametric/policies.rb
80
81
  - lib/parametric/policy_adapter.rb
81
82
  - lib/parametric/registry.rb
@@ -89,6 +90,7 @@ files:
89
90
  - spec/dsl_spec.rb
90
91
  - spec/expand_spec.rb
91
92
  - spec/field_spec.rb
93
+ - spec/nullable_policy_spec.rb
92
94
  - spec/policies_spec.rb
93
95
  - spec/schema_lifecycle_hooks_spec.rb
94
96
  - spec/schema_spec.rb
@@ -115,7 +117,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
115
117
  - !ruby/object:Gem::Version
116
118
  version: '0'
117
119
  requirements: []
118
- rubygems_version: 3.4.18
120
+ rubygems_version: 3.4.22
119
121
  signing_key:
120
122
  specification_version: 4
121
123
  summary: DSL for declaring allowed parameters with options, regexp patern and default
@@ -125,6 +127,7 @@ test_files:
125
127
  - spec/dsl_spec.rb
126
128
  - spec/expand_spec.rb
127
129
  - spec/field_spec.rb
130
+ - spec/nullable_policy_spec.rb
128
131
  - spec/policies_spec.rb
129
132
  - spec/schema_lifecycle_hooks_spec.rb
130
133
  - spec/schema_spec.rb