nxt_schema 1.0.1 → 1.0.2

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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +19 -24
  3. data/README.md +36 -15
  4. data/lib/nxt_schema.rb +5 -2
  5. data/lib/nxt_schema/errors/coercion_error.rb +6 -0
  6. data/lib/nxt_schema/node/any_of.rb +10 -10
  7. data/lib/nxt_schema/node/base.rb +5 -5
  8. data/lib/nxt_schema/node/collection.rb +12 -12
  9. data/lib/nxt_schema/node/error_store.rb +12 -28
  10. data/lib/nxt_schema/node/errors/schema_error.rb +3 -3
  11. data/lib/nxt_schema/node/errors/validation_error.rb +3 -3
  12. data/lib/nxt_schema/node/schema.rb +14 -14
  13. data/lib/nxt_schema/registry.rb +23 -0
  14. data/lib/nxt_schema/registry/proxy.rb +21 -0
  15. data/lib/nxt_schema/template/base.rb +43 -41
  16. data/lib/nxt_schema/template/type_resolver.rb +25 -10
  17. data/lib/nxt_schema/types.rb +7 -4
  18. data/lib/nxt_schema/{missing_input.rb → undefined.rb} +1 -1
  19. data/lib/nxt_schema/validators/attribute.rb +3 -3
  20. data/lib/nxt_schema/validators/equal_to.rb +3 -3
  21. data/lib/nxt_schema/validators/excluded_in.rb +3 -3
  22. data/lib/nxt_schema/validators/excludes.rb +3 -3
  23. data/lib/nxt_schema/validators/greater_than.rb +3 -3
  24. data/lib/nxt_schema/validators/greater_than_or_equal.rb +3 -3
  25. data/lib/nxt_schema/validators/included_in.rb +3 -3
  26. data/lib/nxt_schema/validators/includes.rb +3 -3
  27. data/lib/nxt_schema/validators/less_than.rb +3 -3
  28. data/lib/nxt_schema/validators/less_than_or_equal.rb +3 -3
  29. data/lib/nxt_schema/validators/optional_node.rb +6 -6
  30. data/lib/nxt_schema/validators/pattern.rb +3 -3
  31. data/lib/nxt_schema/validators/query.rb +4 -4
  32. data/lib/nxt_schema/validators/validate_with_proxy.rb +7 -7
  33. data/lib/nxt_schema/version.rb +1 -1
  34. metadata +6 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d1aba2ccbd135921f48a84de3e51d11b0592522b8d9e9e9fd3a5ff188117ffae
4
- data.tar.gz: 1c67ef1beda4a6e6a33bd67bc7a9294c7bfbc14ccf72be3b621748212192c8c0
3
+ metadata.gz: a4076ec4518cc51176684f4bb04fca5bcff3554835016f57cce322debf3e9b8c
4
+ data.tar.gz: 336acbce68af2023b714b2b023d732575138968279efebc74b984b51ff33de13
5
5
  SHA512:
6
- metadata.gz: 34cd6cdacddb969ac3532dc8f52150dc16e8be80b12bf8ceaec9cd147df93547cc02e655eaff1d05eee359b660e1143187adb704fbac91a3f09d4a18ebd28087
7
- data.tar.gz: 5f77d02ed8b601aa255a4b9be082c48f1da0e7fa157561547e7c99a726c8a9d2f34a4c76be78cbd60ec529bce719e0b06e42d6645cbbe18e65facf7de9e7a1fc
6
+ metadata.gz: 4947f05400dd492a8bed83ae2b0c42110c75ebd6fd495bdcdcef10871f7715c6d69797ab95291006df759945551c0f92869e29f5b03f0343af49f4bcf6aa3497
7
+ data.tar.gz: 8ed842b8144aacd64f880e3ff7c74c64a9ae218f598522a60f26fb7a0aa2829fb3deaaf93ea0b8600a6346adb6f921d2e56e2249d1ab18e4b5c6427d25bf8759
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- nxt_schema (1.0.1)
4
+ nxt_schema (1.0.2)
5
5
  activesupport
6
6
  dry-types
7
7
  nxt_init
@@ -10,47 +10,43 @@ PATH
10
10
  GEM
11
11
  remote: https://rubygems.org/
12
12
  specs:
13
- activesupport (6.0.3.4)
13
+ activesupport (6.1.3)
14
14
  concurrent-ruby (~> 1.0, >= 1.0.2)
15
- i18n (>= 0.7, < 2)
16
- minitest (~> 5.1)
17
- tzinfo (~> 1.1)
18
- zeitwerk (~> 2.2, >= 2.2.2)
15
+ i18n (>= 1.6, < 2)
16
+ minitest (>= 5.1)
17
+ tzinfo (~> 2.0)
18
+ zeitwerk (~> 2.3)
19
19
  coderay (1.1.3)
20
- concurrent-ruby (1.1.7)
20
+ concurrent-ruby (1.1.8)
21
21
  diff-lcs (1.4.4)
22
- dry-configurable (0.11.6)
22
+ dry-configurable (0.12.1)
23
23
  concurrent-ruby (~> 1.0)
24
- dry-core (~> 0.4, >= 0.4.7)
25
- dry-equalizer (~> 0.2)
24
+ dry-core (~> 0.5, >= 0.5.0)
26
25
  dry-container (0.7.2)
27
26
  concurrent-ruby (~> 1.0)
28
27
  dry-configurable (~> 0.1, >= 0.1.3)
29
- dry-core (0.4.10)
28
+ dry-core (0.5.0)
30
29
  concurrent-ruby (~> 1.0)
31
- dry-equalizer (0.3.0)
32
30
  dry-inflector (0.2.0)
33
- dry-logic (1.0.8)
31
+ dry-logic (1.1.0)
34
32
  concurrent-ruby (~> 1.0)
35
- dry-core (~> 0.2)
36
- dry-equalizer (~> 0.2)
37
- dry-types (1.4.0)
33
+ dry-core (~> 0.5, >= 0.5)
34
+ dry-types (1.5.1)
38
35
  concurrent-ruby (~> 1.0)
39
36
  dry-container (~> 0.3)
40
- dry-core (~> 0.4, >= 0.4.4)
41
- dry-equalizer (~> 0.3)
37
+ dry-core (~> 0.5, >= 0.5)
42
38
  dry-inflector (~> 0.1, >= 0.1.2)
43
39
  dry-logic (~> 1.0, >= 1.0.2)
44
40
  hirb (0.7.3)
45
- i18n (1.8.5)
41
+ i18n (1.8.9)
46
42
  concurrent-ruby (~> 1.0)
47
43
  method_profiler (2.0.1)
48
44
  hirb (>= 0.6.0)
49
45
  method_source (1.0.0)
50
- minitest (5.14.2)
46
+ minitest (5.14.4)
51
47
  nxt_init (0.1.5)
52
48
  activesupport
53
- nxt_registry (0.3.3)
49
+ nxt_registry (0.3.9)
54
50
  activesupport
55
51
  pry (0.13.1)
56
52
  coderay (~> 1.1)
@@ -69,9 +65,8 @@ GEM
69
65
  diff-lcs (>= 1.2.0, < 2.0)
70
66
  rspec-support (~> 3.10.0)
71
67
  rspec-support (3.10.0)
72
- thread_safe (0.3.6)
73
- tzinfo (1.2.8)
74
- thread_safe (~> 0.1)
68
+ tzinfo (2.0.4)
69
+ concurrent-ruby (~> 1.0)
75
70
  zeitwerk (2.4.2)
76
71
 
77
72
  PLATFORMS
data/README.md CHANGED
@@ -128,7 +128,7 @@ end
128
128
 
129
129
  result = schema.apply(input: {})
130
130
  result.errors # => {}
131
- result.output # => {:email=>NxtSchema::MissingInput}
131
+ result.output # => {:email=>NxtSchema::Undefined}
132
132
  ```
133
133
 
134
134
  ```ruby
@@ -225,10 +225,42 @@ This is suitable to validate and coerce your query params.
225
225
  NxtSchema.params do
226
226
  required(:effective_at, :DateTime) # would resolve to Types::Params::DateTime
227
227
  required(:test, :String) # The :String will resolve to NxtSchema::Types::Nominal::String
228
- required(:advanced, NxtSchema::Types::Params::Bool) # long version of required(:advanced, :Bool)
228
+ required(:advanced, NxtSchema::Types::Registry::Bool) # long version of required(:advanced, :Bool)
229
229
  end
230
230
  ```
231
231
 
232
+ #### NxtSchema::Registry
233
+
234
+ To make use of NxtSchema.params in your controller you can simply include the `NxtSchema::Registry` to easily register
235
+ and apply schemas:
236
+
237
+ ```ruby
238
+ class UsersController < ApplicationController
239
+ include NxtSchema::Registry
240
+
241
+ # register the schema for the :create action
242
+ schemas.register(
243
+ :create,
244
+ NxtSchema.params do
245
+ required(:first_name, :String)
246
+ required(:last_name, :String)
247
+ end
248
+ )
249
+
250
+ def create
251
+ User.create!(**create_params)
252
+ end
253
+
254
+ private
255
+
256
+ def create_params
257
+ # apply the registered schema
258
+ schemas.apply!(:create, params.fetch(:user))
259
+ end
260
+ end
261
+
262
+ ```
263
+
232
264
  #### Custom types
233
265
 
234
266
  You can also register custom types. In order to check out all the cool things you can do with dry types you should
@@ -486,16 +518,5 @@ The gem is available as open source under the terms of the [MIT License](https:/
486
518
  --> Would be cool to register things for the schema only
487
519
  --> Would be cool if this was extendable
488
520
  - Do we need all off in order to combine multiple schemas?
489
- - Think about a good implementation of params framework for controllers
490
-
491
- ```ruby
492
- PARAMS = NxtRegistry::Registry.new do
493
- register(:create) do
494
- NxtSchema.params do
495
-
496
- end
497
- end
498
- end
499
-
500
- PARAMS.resolve(:create).apply(input: params)
501
- ```
521
+ - Allow custom errors
522
+ - Spec inheritance of params
data/lib/nxt_schema.rb CHANGED
@@ -8,10 +8,11 @@ require 'yaml'
8
8
  require_relative 'nxt_schema/types'
9
9
  require_relative 'nxt_schema/callable'
10
10
  require_relative 'nxt_schema/node'
11
- require_relative 'nxt_schema/missing_input'
11
+ require_relative 'nxt_schema/undefined'
12
12
  require_relative 'nxt_schema/error'
13
13
  require_relative 'nxt_schema/errors/invalid'
14
14
  require_relative 'nxt_schema/errors/invalid_options'
15
+ require_relative 'nxt_schema/errors/coercion_error'
15
16
 
16
17
  require_relative 'nxt_schema/validators/registry'
17
18
  require_relative 'nxt_schema/validators/validate_with_proxy'
@@ -52,6 +53,8 @@ require_relative 'nxt_schema/node/leaf'
52
53
  require_relative 'nxt_schema/node/collection'
53
54
  require_relative 'nxt_schema/node/schema'
54
55
  require_relative 'nxt_schema/dsl'
56
+ require_relative 'nxt_schema/registry/proxy'
57
+ require_relative 'nxt_schema/registry'
55
58
 
56
59
  module NxtSchema
57
60
  extend Dsl
@@ -65,7 +68,7 @@ module NxtSchema
65
68
  end
66
69
 
67
70
  def register_type(key, type)
68
- NxtSchema::Types.const_set(key.to_s, type)
71
+ NxtSchema::Types.registry(:types).register(key, type)
69
72
  end
70
73
 
71
74
  # Load default messages
@@ -0,0 +1,6 @@
1
+ module NxtSchema
2
+ module Errors
3
+ class CoercionError < Error
4
+ end
5
+ end
6
+ end
@@ -2,17 +2,17 @@ module NxtSchema
2
2
  module Node
3
3
  class AnyOf < Node::Base
4
4
  def valid?
5
- valid_application.present?
5
+ valid_node.present?
6
6
  end
7
7
 
8
8
  def call
9
- child_applications.map(&:call)
9
+ child_nodes.map(&:call)
10
10
 
11
11
  if valid?
12
- self.output = valid_application.output
12
+ self.output = valid_node.output
13
13
  else
14
- child_applications.each do |application|
15
- merge_errors(application)
14
+ child_nodes.each do |node|
15
+ merge_errors(node)
16
16
  end
17
17
  end
18
18
 
@@ -21,14 +21,14 @@ module NxtSchema
21
21
 
22
22
  private
23
23
 
24
- delegate :[], to: :child_applications
24
+ delegate :[], to: :child_nodes
25
25
 
26
- def valid_application
27
- child_applications.find(&:valid?)
26
+ def valid_node
27
+ child_nodes.find(&:valid?)
28
28
  end
29
29
 
30
- def child_applications
31
- @child_applications ||= nodes.map { |node| node.build_application(input: input, context: context, parent: self) }
30
+ def child_nodes
31
+ @child_nodes ||= nodes.map { |node| node.build_node(input: input, context: context, parent: self) }
32
32
  end
33
33
 
34
34
  def nodes
@@ -1,7 +1,7 @@
1
1
  module NxtSchema
2
2
  module Node
3
3
  class Base
4
- def initialize(node:, input: MissingInput.new, parent:, context:, error_key:)
4
+ def initialize(node:, input: Undefined.new, parent:, context:, error_key:)
5
5
  @node = node
6
6
  @input = input
7
7
  @parent = parent
@@ -44,8 +44,8 @@ module NxtSchema
44
44
  errors.add_schema_error(message: error)
45
45
  end
46
46
 
47
- def merge_errors(application)
48
- errors.merge_errors(application)
47
+ def merge_errors(node)
48
+ errors.merge_errors(node)
49
49
  end
50
50
 
51
51
  def run_validations
@@ -71,10 +71,10 @@ module NxtSchema
71
71
  attr_writer :coerced, :root
72
72
 
73
73
  def coerce_input
74
- output = input.is_a?(MissingInput) && node.omnipresent? ? input : node.type[input]
74
+ output = input.is_a?(Undefined) && node.omnipresent? ? input : node.type.call(input)
75
75
  self.output = output
76
76
 
77
- rescue Dry::Types::CoercionError => error
77
+ rescue Dry::Types::CoercionError, NxtSchema::Errors::CoercionError => error
78
78
  add_schema_error(error.message)
79
79
  end
80
80
 
@@ -3,20 +3,20 @@ module NxtSchema
3
3
  class Collection < Node::Base
4
4
  def call
5
5
  apply_on_evaluators
6
- child_applications # build applications here so we can access them even when invalid
6
+ child_nodes # build nodes here so we can access them even when invalid
7
7
  return self if maybe_evaluator_applies?
8
8
 
9
9
  coerce_input
10
10
  validate_filled
11
11
  return self unless valid?
12
12
 
13
- child_applications.each_with_index do |item, index|
14
- current_application = item.call
13
+ child_nodes.each_with_index do |item, index|
14
+ child_node = item.call
15
15
 
16
- if !current_application.valid?
17
- merge_errors(current_application)
16
+ if !child_node.valid?
17
+ merge_errors(child_node)
18
18
  else
19
- output[index] = current_application.output
19
+ output[index] = child_node.output
20
20
  end
21
21
  end
22
22
 
@@ -26,7 +26,7 @@ module NxtSchema
26
26
  self
27
27
  end
28
28
 
29
- delegate :[], to: :child_applications
29
+ delegate :[], to: :child_nodes
30
30
 
31
31
  private
32
32
 
@@ -34,19 +34,19 @@ module NxtSchema
34
34
  add_schema_error('is not allowed to be empty') if input.blank? && !maybe_evaluator_applies?
35
35
  end
36
36
 
37
- def child_applications
38
- @child_applications ||= begin
37
+ def child_nodes
38
+ @child_nodes ||= begin
39
39
  return [] unless input.respond_to?(:each_with_index)
40
40
 
41
41
  input.each_with_index.map do |item, index|
42
- build_child_application(item, index)
42
+ build_child_node(item, index)
43
43
  end
44
44
  end
45
45
 
46
46
  end
47
47
 
48
- def build_child_application(item, error_key)
49
- sub_node.build_application(input: item, context: context, parent: self, error_key: error_key)
48
+ def build_child_node(item, error_key)
49
+ sub_node.build_node(input: item, context: context, parent: self, error_key: error_key)
50
50
  end
51
51
 
52
52
  def sub_node
@@ -1,18 +1,18 @@
1
1
  module NxtSchema
2
2
  module Node
3
3
  class ErrorStore < ::Hash
4
- def initialize(application)
4
+ def initialize(node)
5
5
  super()
6
- @application = application
6
+ @node = node
7
7
  end
8
8
 
9
- attr_reader :application
9
+ attr_reader :node
10
10
 
11
11
  def add_schema_error(message:)
12
12
  add_error(
13
- application,
13
+ node,
14
14
  NxtSchema::Node::Errors::SchemaError.new(
15
- application: application,
15
+ node: node,
16
16
  message: message
17
17
  )
18
18
  )
@@ -20,38 +20,22 @@ module NxtSchema
20
20
 
21
21
  def add_validation_error(message:)
22
22
  add_error(
23
- application,
23
+ node,
24
24
  NxtSchema::Node::Errors::ValidationError.new(
25
- application: application,
25
+ node: node,
26
26
  message: message
27
27
  )
28
28
  )
29
29
  end
30
30
 
31
- def merge_errors(application)
32
- merge!(application.errors)
31
+ def merge_errors(node)
32
+ merge!(node.errors)
33
33
  end
34
34
 
35
- def add_error(application, error)
36
- self[application.error_key] ||= []
37
- self[application.error_key] << error
35
+ def add_error(node, error)
36
+ self[node.error_key] ||= []
37
+ self[node.error_key] << error
38
38
  end
39
-
40
- # def schema_errors
41
- # inject({}) do |acc, (k, v)|
42
- # errors = v.select { |e| e.is_a?(NxtSchema::Node::Errors::SchemaError) }
43
- # acc[k] = errors if errors.any?
44
- # acc
45
- # end
46
- # end
47
- #
48
- # def validation_errors
49
- # inject({}) do |acc, (k, v)|
50
- # errors = v.select { |e| e.is_a?(NxtSchema::Node::Errors::ValidationError) }
51
- # acc[k] = errors if errors.any?
52
- # acc
53
- # end
54
- # end
55
39
  end
56
40
  end
57
41
  end
@@ -2,12 +2,12 @@ module NxtSchema
2
2
  module Node
3
3
  module Errors
4
4
  class SchemaError < ::String
5
- def initialize(application:, message:)
5
+ def initialize(node:, message:)
6
6
  super(message)
7
- @application = application
7
+ @node = node
8
8
  end
9
9
 
10
- attr_reader :application
10
+ attr_reader :node
11
11
  end
12
12
  end
13
13
  end
@@ -2,12 +2,12 @@ module NxtSchema
2
2
  module Node
3
3
  module Errors
4
4
  class ValidationError < ::String
5
- def initialize(application:, message:)
5
+ def initialize(node:, message:)
6
6
  super(message)
7
- @application = application
7
+ @node = node
8
8
  end
9
9
 
10
- attr_reader :application
10
+ attr_reader :node
11
11
  end
12
12
  end
13
13
  end
@@ -3,7 +3,7 @@ module NxtSchema
3
3
  class Schema < Node::Base
4
4
  def call
5
5
  apply_on_evaluators
6
- child_applications # build applications here so we can access them even when invalid
6
+ child_nodes # build nodes here so we can access them even when invalid
7
7
  return self if maybe_evaluator_applies?
8
8
 
9
9
  coerce_input
@@ -12,13 +12,13 @@ module NxtSchema
12
12
  flag_missing_keys
13
13
  apply_additional_keys_strategy
14
14
 
15
- child_applications.each do |key, child|
16
- current_application = child.call
15
+ child_nodes.each do |key, child|
16
+ current_node = child.call
17
17
 
18
- if !current_application.valid?
19
- merge_errors(current_application)
18
+ if !current_node.valid?
19
+ merge_errors(current_node)
20
20
  else
21
- output[key] = current_application.output
21
+ output[key] = current_node.output
22
22
  end
23
23
  end
24
24
 
@@ -28,7 +28,7 @@ module NxtSchema
28
28
  self
29
29
  end
30
30
 
31
- delegate :[], to: :child_applications
31
+ delegate :[], to: :child_nodes
32
32
 
33
33
  private
34
34
 
@@ -88,22 +88,22 @@ module NxtSchema
88
88
  node.additional_keys_strategy == :restrict
89
89
  end
90
90
 
91
- def child_applications
92
- @child_applications ||= begin
91
+ def child_nodes
92
+ @child_nodes ||= begin
93
93
  keys.inject({}) do |acc, key|
94
- child_application = build_child_application(key)
95
- acc[key] = child_application if child_application.present?
94
+ child_node = build_child_node(key)
95
+ acc[key] = child_node if child_node.present?
96
96
  acc
97
97
  end
98
98
  end
99
99
  end
100
100
 
101
- def build_child_application(key)
101
+ def build_child_node(key)
102
102
  sub_node = node.sub_nodes[key]
103
103
  return unless sub_node.present?
104
104
 
105
- value = input_has_key?(input, key) ? input[key] : MissingInput.new
106
- sub_node.build_application(input: value, context: context, parent: self)
105
+ value = input_has_key?(input, key) ? input[key] : Undefined.new
106
+ sub_node.build_node(input: value, context: context, parent: self)
107
107
  end
108
108
 
109
109
  def input_has_key?(input, key)
@@ -0,0 +1,23 @@
1
+ module NxtSchema
2
+ module Registry
3
+ module ClassMethods
4
+ def schemas
5
+ @schemas ||= NxtSchema::Registry::Proxy.new(self)
6
+ end
7
+
8
+ def inherited(subclass)
9
+ schemas.each do |key, schema|
10
+ subclass.schemas.register(key, schema)
11
+ end
12
+
13
+ super
14
+ end
15
+ end
16
+
17
+ def self.included(base)
18
+ base.extend(ClassMethods)
19
+
20
+ delegate :schemas, to: :class
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,21 @@
1
+ module NxtSchema
2
+ module Registry
3
+ class Proxy
4
+ def initialize(namespace)
5
+ @registry = ::NxtRegistry::Registry.new(namespace, call: false)
6
+ end
7
+
8
+ attr_reader :registry
9
+
10
+ delegate_missing_to :registry
11
+
12
+ def apply(key, input)
13
+ resolve!(key).apply(input: input)
14
+ end
15
+
16
+ def apply!(key, input)
17
+ resolve!(key).apply!(input: input)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -21,40 +21,42 @@ module NxtSchema
21
21
  resolve_type_system
22
22
  resolve_type(type)
23
23
  resolve_additional_keys_strategy
24
- application_class # memoize
24
+ node_class # memoize
25
25
  configure(&block) if block_given?
26
26
  end
27
27
 
28
28
  attr_accessor :name,
29
- :parent_node,
30
- :options,
31
- :type,
32
- :root_node,
33
- :additional_keys_strategy
29
+ :parent_node,
30
+ :options,
31
+ :type,
32
+ :root_node,
33
+ :additional_keys_strategy
34
34
 
35
35
  attr_reader :type_system,
36
- :path,
37
- :context,
38
- :meta,
39
- :on_evaluators,
40
- :maybe_evaluators,
41
- :validations,
42
- :configuration,
43
- :key_transformer
36
+ :path,
37
+ :context,
38
+ :meta,
39
+ :on_evaluators,
40
+ :maybe_evaluators,
41
+ :validations,
42
+ :configuration,
43
+ :key_transformer
44
44
 
45
- def apply(input: MissingInput.new, context: self.context, parent: nil, error_key: nil)
46
- build_application(input: input, context: context, parent: parent, error_key: error_key).call
45
+ def apply(input: Undefined.new, context: self.context, parent: nil, error_key: nil)
46
+ build_node(input: input, context: context, parent: parent, error_key: error_key).call
47
47
  end
48
48
 
49
- def apply!(input: MissingInput.new, context: self.context, parent: nil, error_key: nil)
50
- result = build_application(input: input, context: context, parent: parent, error_key: error_key).call
51
- return result if parent || result.errors.empty?
49
+ def apply!(input: Undefined.new, context: self.context, parent: nil, error_key: nil)
50
+ result = build_node(input: input, context: context, parent: parent, error_key: error_key).call
51
+ return result if parent
52
52
 
53
- raise NxtSchema::Errors::Invalid.new(result)
53
+ raise NxtSchema::Errors::Invalid.new(result) if result.errors.any?
54
+
55
+ result.output
54
56
  end
55
57
 
56
- def build_application(input: MissingInput.new, context: self.context, parent: nil, error_key: nil)
57
- application_class.new(
58
+ def build_node(input: Undefined.new, context: self.context, parent: nil, error_key: nil)
59
+ node_class.new(
58
60
  node: self,
59
61
  input: input,
60
62
  parent: parent,
@@ -75,7 +77,7 @@ module NxtSchema
75
77
  @omnipresent
76
78
  end
77
79
 
78
- def default(value = NxtSchema::MissingInput.new, &block)
80
+ def default(value = NxtSchema::Undefined.new, &block)
79
81
  value = missing_input?(value) ? block : value
80
82
  condition = ->(input) { missing_input?(input) || input.nil? }
81
83
  on(condition, value)
@@ -83,36 +85,36 @@ module NxtSchema
83
85
  self
84
86
  end
85
87
 
86
- def on(condition, value = NxtSchema::MissingInput.new, &block)
88
+ def on(condition, value = NxtSchema::Undefined.new, &block)
87
89
  value = missing_input?(value) ? block : value
88
90
  on_evaluators << OnEvaluator.new(condition: condition, value: value)
89
91
 
90
92
  self
91
93
  end
92
94
 
93
- def maybe(value = NxtSchema::MissingInput.new, &block)
95
+ def maybe(value = NxtSchema::Undefined.new, &block)
94
96
  value = missing_input?(value) ? block : value
95
97
  maybe_evaluators << MaybeEvaluator.new(value: value)
96
98
 
97
99
  self
98
100
  end
99
101
 
100
- def validate(key = NxtSchema::MissingInput.new, *args, &block)
102
+ def validate(key = NxtSchema::Undefined.new, *args, &block)
101
103
  # TODO: This does not really work with all kinds of chaining combinations yet!
102
104
 
103
105
  validator = if key.is_a?(Symbol)
104
- validator(key, *args)
105
- elsif key.respond_to?(:call)
106
- key
107
- elsif block_given?
108
- if key.is_a?(NxtSchema::MissingInput)
109
- block
110
- else
111
- configure(&block)
112
- end
113
- else
114
- raise ArgumentError, "Don't know how to resolve validator from: #{key} with: #{args} #{block}"
115
- end
106
+ validator(key, *args)
107
+ elsif key.respond_to?(:call)
108
+ key
109
+ elsif block_given?
110
+ if key.is_a?(NxtSchema::Undefined)
111
+ block
112
+ else
113
+ configure(&block)
114
+ end
115
+ else
116
+ raise ArgumentError, "Don't know how to resolve validator from: #{key} with: #{args} #{block}"
117
+ end
116
118
 
117
119
  register_validator(validator)
118
120
 
@@ -150,8 +152,8 @@ module NxtSchema
150
152
  end
151
153
  end
152
154
 
153
- def application_class
154
- @application_class ||= "NxtSchema::Node::#{self.class.name.demodulize}".constantize
155
+ def node_class
156
+ @node_class ||= "NxtSchema::Node::#{self.class.name.demodulize}".constantize
155
157
  end
156
158
 
157
159
  def configure(&block)
@@ -201,7 +203,7 @@ module NxtSchema
201
203
  end
202
204
 
203
205
  def missing_input?(value)
204
- value.is_a? MissingInput
206
+ value.is_a? Undefined
205
207
  end
206
208
 
207
209
  def resolve_key_transformer
@@ -4,21 +4,36 @@ module NxtSchema
4
4
  def resolve(type_system, type)
5
5
  @resolve ||= {}
6
6
  @resolve[type] ||= begin
7
- if type.is_a?(Dry::Types::Type)
7
+ if type.is_a?(Symbol)
8
+ resolve_type_from_symbol(type, type_system)
9
+ elsif type.respond_to?(:call)
8
10
  type
9
11
  else
10
- # Try to resolve in type system
11
- type = type_system.const_get(type.to_s.classify)
12
-
13
- if type.is_a?(Dry::Types::Type)
14
- type
15
- else
16
- # in case it does not exist fallback to Types::Nominal
17
- "NxtSchema::Types::Nominal::#{type.to_s.classify}".constantize
18
- end
12
+ raise_type_not_resolvable_error(type)
19
13
  end
14
+ rescue NxtRegistry::Errors::KeyNotRegisteredError => error
15
+ raise_type_not_resolvable_error(type)
20
16
  end
21
17
  end
18
+
19
+ private
20
+
21
+ def resolve_type_from_symbol(type, type_system)
22
+ classified_type = type.to_s.classify
23
+
24
+ return type_system.const_get(classified_type) if type_defined_in_type_system?(type, type_system)
25
+ return NxtSchema::Types::Nominal.const_get(classified_type) if type_defined_in_type_system?(type, NxtSchema::Types::Nominal)
26
+
27
+ NxtSchema::Types.registry(:types).resolve!(type)
28
+ end
29
+
30
+ def type_defined_in_type_system?(type, type_system)
31
+ type_system.constants.include?(type)
32
+ end
33
+
34
+ def raise_type_not_resolvable_error(type)
35
+ raise ArgumentError, "Can't resolve type: #{type}"
36
+ end
22
37
  end
23
38
  end
24
39
  end
@@ -1,10 +1,13 @@
1
1
  module NxtSchema
2
2
  module Types
3
3
  include Dry.Types()
4
+ extend NxtRegistry
4
5
 
5
- StrippedString = Strict::String.constructor(->(string) { string&.strip })
6
- LengthyStrippedString = StrippedString.constrained(min_size: 1)
7
- Enums = -> (*values) { Strict::String.enum(*values) } # Use as NxtSchema::Types::Enums[*ROLES]
8
- SymbolizedEnums = -> (*values) { Coercible::Symbol.enum(*values) } # Use as NxtSchema::Types::SymboleEnums[*ROLES]
6
+ registry(:types, call: false) do
7
+ register(:StrippedString, Strict::String.constructor(->(string) { string&.strip }))
8
+ register(:LengthyStrippedString, resolve!(:StrippedString).constrained(min_size: 1))
9
+ register(:Enum, -> (*values) { Strict::String.enum(*values) })
10
+ register(:SymbolizedEnum, -> (*values) { Coercible::Symbol.enum(*values) })
11
+ end
9
12
  end
10
13
  end
@@ -1,5 +1,5 @@
1
1
  module NxtSchema
2
- class MissingInput
2
+ class Undefined
3
3
  def inspect
4
4
  self.class.name
5
5
  end
@@ -12,15 +12,15 @@ module NxtSchema
12
12
  # Query any attribute on a value with validator(:attribute, :size, ->(s) { s < 7 })
13
13
 
14
14
  def build
15
- lambda do |application, value|
15
+ lambda do |node, value|
16
16
  raise ArgumentError, "#{value} does not respond to query: #{method}" unless value.respond_to?(method)
17
17
 
18
18
  if expectation.call(value.send(method))
19
19
  true
20
20
  else
21
- application.add_error(
21
+ node.add_error(
22
22
  translate_error(
23
- application.locale,
23
+ node.locale,
24
24
  attribute: value,
25
25
  attribute_name: method,
26
26
  value: value.send(method)
@@ -12,15 +12,15 @@ module NxtSchema
12
12
  # Query for equality validator(:eql, -> { 3 * 3 * 60 })
13
13
 
14
14
  def build
15
- lambda do |application, value|
15
+ lambda do |node, value|
16
16
  expected_value = Callable.new(expectation, nil, value).call
17
17
 
18
18
  if value == expected_value
19
19
  true
20
20
  else
21
- application.add_error(
21
+ node.add_error(
22
22
  translate_error(
23
- application.locale,
23
+ node.locale,
24
24
  actual: value,
25
25
  expected: expected_value
26
26
  )
@@ -9,12 +9,12 @@ module NxtSchema
9
9
  attr_reader :target
10
10
 
11
11
  def build
12
- lambda do |application, value|
12
+ lambda do |node, value|
13
13
  if target.exclude?(value)
14
14
  true
15
15
  else
16
- message = translate_error(application.locale, target: target, value: value)
17
- application.add_error(message)
16
+ message = translate_error(node.locale, target: target, value: value)
17
+ node.add_error(message)
18
18
  end
19
19
  end
20
20
  end
@@ -9,12 +9,12 @@ module NxtSchema
9
9
  attr_reader :target
10
10
 
11
11
  def build
12
- lambda do |application, value|
12
+ lambda do |node, value|
13
13
  if value.exclude?(target)
14
14
  true
15
15
  else
16
- message = translate_error(application.locale, target: target, value: value)
17
- application.add_error(message)
16
+ message = translate_error(node.locale, target: target, value: value)
17
+ node.add_error(message)
18
18
  end
19
19
  end
20
20
  end
@@ -9,12 +9,12 @@ module NxtSchema
9
9
  attr_reader :threshold
10
10
 
11
11
  def build
12
- lambda do |application, value|
12
+ lambda do |node, value|
13
13
  if value > threshold
14
14
  true
15
15
  else
16
- message = translate_error(application.locale, value: value, threshold: threshold)
17
- application.add_error(message)
16
+ message = translate_error(node.locale, value: value, threshold: threshold)
17
+ node.add_error(message)
18
18
  end
19
19
  end
20
20
  end
@@ -9,12 +9,12 @@ module NxtSchema
9
9
  attr_reader :threshold
10
10
 
11
11
  def build
12
- lambda do |application, value|
12
+ lambda do |node, value|
13
13
  if value >= threshold
14
14
  true
15
15
  else
16
- message = translate_error(application.locale, value: value, threshold: threshold)
17
- application.add_error(message)
16
+ message = translate_error(node.locale, value: value, threshold: threshold)
17
+ node.add_error(message)
18
18
  end
19
19
  end
20
20
  end
@@ -9,12 +9,12 @@ module NxtSchema
9
9
  attr_reader :target
10
10
 
11
11
  def build
12
- lambda do |application, value|
12
+ lambda do |node, value|
13
13
  if target.include?(value)
14
14
  true
15
15
  else
16
- message = translate_error(application.locale, value: value, target: target)
17
- application.add_error(message)
16
+ message = translate_error(node.locale, value: value, target: target)
17
+ node.add_error(message)
18
18
  end
19
19
  end
20
20
  end
@@ -9,12 +9,12 @@ module NxtSchema
9
9
  attr_reader :target
10
10
 
11
11
  def build
12
- lambda do |application, value|
12
+ lambda do |node, value|
13
13
  if value.include?(target)
14
14
  true
15
15
  else
16
- message = translate_error(application.locale, value: value, target: target)
17
- application.add_error(message)
16
+ message = translate_error(coerced?.locale, value: value, target: target)
17
+ node.add_error(message)
18
18
  end
19
19
  end
20
20
  end
@@ -9,12 +9,12 @@ module NxtSchema
9
9
  attr_reader :threshold
10
10
 
11
11
  def build
12
- lambda do |application, value|
12
+ lambda do |node, value|
13
13
  if value < threshold
14
14
  true
15
15
  else
16
- message = translate_error(application.locale, value: value, threshold: threshold)
17
- application.add_error(message)
16
+ message = translate_error(node.locale, value: value, threshold: threshold)
17
+ node.add_error(message)
18
18
  end
19
19
  end
20
20
  end
@@ -9,12 +9,12 @@ module NxtSchema
9
9
  attr_reader :threshold
10
10
 
11
11
  def build
12
- lambda do |application, value|
12
+ lambda do |node, value|
13
13
  if value <= threshold
14
14
  true
15
15
  else
16
- message = translate_error(application.locale, value: value, threshold: threshold)
17
- application.add_error(message)
16
+ message = translate_error(node.locale, value: value, threshold: threshold)
17
+ node.add_error(message)
18
18
  end
19
19
  end
20
20
  end
@@ -10,20 +10,20 @@ module NxtSchema
10
10
  attr_reader :conditional, :missing_key
11
11
 
12
12
  def build
13
- lambda do |application, value|
14
- args = [application, value]
13
+ lambda do |node, value|
14
+ args = [node, value]
15
15
 
16
16
  return if conditional.call(*args.take(conditional.arity))
17
- return if application.send(:keys).include?(missing_key.to_sym)
17
+ return if node.send(:keys).include?(missing_key.to_sym)
18
18
 
19
19
  message = ErrorMessages.resolve(
20
- application.locale,
20
+ node.locale,
21
21
  :required_key_missing,
22
22
  key: missing_key,
23
- target: application.input
23
+ target: node.input
24
24
  )
25
25
 
26
- application.add_error(message)
26
+ node.add_error(message)
27
27
  end
28
28
  end
29
29
  end
@@ -9,12 +9,12 @@ module NxtSchema
9
9
  attr_reader :pattern
10
10
 
11
11
  def build
12
- lambda do |application, value|
12
+ lambda do |node, value|
13
13
  if value.match(pattern)
14
14
  true
15
15
  else
16
- message = translate_error(application.locale, value: value, pattern: pattern)
17
- application.add_error(message)
16
+ message = translate_error(node.locale, value: value, pattern: pattern)
17
+ node.add_error(message)
18
18
  false
19
19
  end
20
20
  end
@@ -8,18 +8,18 @@ module NxtSchema
8
8
  register_as :query
9
9
  attr_reader :method
10
10
 
11
- # Query a boolean method on you value => application(:test, :String).validate(:query, :good_enough?)
11
+ # Query a boolean method on you value => node(:test, :String).validate(:query, :good_enough?)
12
12
  # => Would be valid if value.good_enough? is truthy
13
13
 
14
14
  def build
15
- lambda do |application, value|
15
+ lambda do |node, value|
16
16
  raise ArgumentError, "#{value} does not respond to query: #{method}" unless value.respond_to?(method)
17
17
 
18
18
  if value.send(method)
19
19
  true
20
20
  else
21
- message = translate_error(application.locale, value: value, actual: value.send(method), query: method)
22
- application.add_error(message)
21
+ message = translate_error(node.locale, value: value, actual: value.send(method), query: method)
22
+ node.add_error(message)
23
23
  end
24
24
  end
25
25
  end
@@ -1,14 +1,14 @@
1
1
  module NxtSchema
2
2
  module Validator
3
3
  class ValidateWithProxy
4
- def initialize(application)
5
- @application = application
4
+ def initialize(node)
5
+ @node = node
6
6
  @aggregated_errors = []
7
7
  end
8
8
 
9
- attr_reader :application
9
+ attr_reader :node
10
10
 
11
- delegate_missing_to :application
11
+ delegate_missing_to :node
12
12
 
13
13
  def validate(&block)
14
14
  result = instance_exec(&block)
@@ -24,7 +24,7 @@ module NxtSchema
24
24
 
25
25
  def copy_aggregated_errors_to_node
26
26
  aggregated_errors.each do |error|
27
- application.add_error(error)
27
+ node.add_error(error)
28
28
  end
29
29
  end
30
30
 
@@ -33,8 +33,8 @@ module NxtSchema
33
33
  attr_reader :aggregated_errors
34
34
 
35
35
  def validator(key, *args)
36
- validator = application.node.send(:validator, key, *args)
37
- validator.call(self, application.input)
36
+ validator = node.node.send(:validator, key, *args)
37
+ validator.call(self, node.input)
38
38
  end
39
39
  end
40
40
  end
@@ -1,3 +1,3 @@
1
1
  module NxtSchema
2
- VERSION = "1.0.1"
2
+ VERSION = "1.0.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nxt_schema
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andreas Robecke
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-12-03 00:00:00.000000000 Z
11
+ date: 2021-03-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -158,9 +158,9 @@ files:
158
158
  - lib/nxt_schema/callable.rb
159
159
  - lib/nxt_schema/dsl.rb
160
160
  - lib/nxt_schema/error.rb
161
+ - lib/nxt_schema/errors/coercion_error.rb
161
162
  - lib/nxt_schema/errors/invalid.rb
162
163
  - lib/nxt_schema/errors/invalid_options.rb
163
- - lib/nxt_schema/missing_input.rb
164
164
  - lib/nxt_schema/node.rb
165
165
  - lib/nxt_schema/node/any_of.rb
166
166
  - lib/nxt_schema/node/base.rb
@@ -170,6 +170,8 @@ files:
170
170
  - lib/nxt_schema/node/errors/validation_error.rb
171
171
  - lib/nxt_schema/node/leaf.rb
172
172
  - lib/nxt_schema/node/schema.rb
173
+ - lib/nxt_schema/registry.rb
174
+ - lib/nxt_schema/registry/proxy.rb
173
175
  - lib/nxt_schema/template/any_of.rb
174
176
  - lib/nxt_schema/template/base.rb
175
177
  - lib/nxt_schema/template/collection.rb
@@ -182,6 +184,7 @@ files:
182
184
  - lib/nxt_schema/template/type_resolver.rb
183
185
  - lib/nxt_schema/template/type_system_resolver.rb
184
186
  - lib/nxt_schema/types.rb
187
+ - lib/nxt_schema/undefined.rb
185
188
  - lib/nxt_schema/validators/attribute.rb
186
189
  - lib/nxt_schema/validators/equal_to.rb
187
190
  - lib/nxt_schema/validators/error_messages.rb