nxt_schema 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
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