definition 0.6.1 → 0.7.0
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 +4 -4
- data/.circleci/config.yml +18 -8
- data/.rubocop.yml +1 -1
- data/Changelog.md +13 -1
- data/Gemfile.lock +30 -49
- data/README.md +18 -0
- data/config/locales/en.yml +12 -13
- data/lib/definition/conform_error.rb +8 -8
- data/lib/definition/conform_result.rb +1 -1
- data/lib/definition/dsl.rb +3 -5
- data/lib/definition/key_conform_error.rb +2 -2
- data/lib/definition/types/and.rb +5 -0
- data/lib/definition/types/base.rb +5 -0
- data/lib/definition/types/each.rb +5 -0
- data/lib/definition/types/error_renderers/lambda.rb +15 -0
- data/lib/definition/types/error_renderers/leaf.rb +18 -0
- data/lib/definition/types/error_renderers/standard.rb +39 -0
- data/lib/definition/types/include.rb +2 -1
- data/lib/definition/types/lambda.rb +46 -15
- data/lib/definition/types/or.rb +8 -2
- data/lib/definition/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9de3bc4f221f0a67beb7c82f3d7bacfa86ab332cfc3ab7efe3f35bd6efeeeaca
|
4
|
+
data.tar.gz: a11b488ecb7fc5e3b2956dbb14c533631936b78d613f6f4a68c58e584cc25faa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cc464d58c56ef306fdc83868be3f67a7151c64e17f9f28d652584c94f73d2ce083308c1fd1c152bc667d57989f0e7fcbaea0e4a89a9aa30e9fb6093bfab18787
|
7
|
+
data.tar.gz: cad0aa2a4165e5ea329751dc8ded8a61f943e110a30d930afbcfec3b2ba2ea7686dccbe41ef322906fb56c8ab23df65f83913d794933d29a3f7907ec0d3e23db
|
data/.circleci/config.yml
CHANGED
@@ -5,26 +5,32 @@ version: 2.1
|
|
5
5
|
# Orbs are reusable packages of CircleCI configuration that you may share across projects, enabling you to create encapsulated, parameterized commands, jobs, and executors that can be used across multiple projects.
|
6
6
|
# See: https://circleci.com/docs/2.0/orb-intro/
|
7
7
|
orbs:
|
8
|
-
ruby: circleci/ruby@1.
|
8
|
+
ruby: circleci/ruby@1.4.0
|
9
9
|
|
10
10
|
# Define a job to be invoked later in a workflow.
|
11
11
|
# See: https://circleci.com/docs/2.0/configuration-reference/#jobs
|
12
12
|
jobs:
|
13
13
|
test:
|
14
14
|
parameters:
|
15
|
-
|
15
|
+
ruby_version:
|
16
16
|
type: string
|
17
17
|
docker:
|
18
|
-
- image:
|
18
|
+
- image: cimg/base:stable
|
19
19
|
steps:
|
20
|
+
- ruby/install:
|
21
|
+
version: << parameters.ruby_version >>
|
20
22
|
- checkout
|
21
|
-
-
|
23
|
+
- run: rm Gemfile.lock
|
24
|
+
- run: gem install bundler
|
25
|
+
- run: bundle install
|
22
26
|
- ruby/rspec-test
|
23
|
-
|
27
|
+
linting:
|
24
28
|
docker:
|
25
|
-
- image: 'cimg/
|
29
|
+
- image: 'cimg/base:stable'
|
26
30
|
steps:
|
27
31
|
- checkout
|
32
|
+
- ruby/install:
|
33
|
+
version: "3.0"
|
28
34
|
- ruby/install-deps
|
29
35
|
- ruby/rubocop-check:
|
30
36
|
format: progress
|
@@ -39,5 +45,9 @@ workflows:
|
|
39
45
|
- test:
|
40
46
|
matrix:
|
41
47
|
parameters:
|
42
|
-
|
43
|
-
|
48
|
+
ruby_version:
|
49
|
+
- "2.6"
|
50
|
+
- "2.7"
|
51
|
+
- "3.0"
|
52
|
+
- "jruby-9.3.3.0"
|
53
|
+
- linting
|
data/.rubocop.yml
CHANGED
data/Changelog.md
CHANGED
@@ -4,7 +4,19 @@ 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
|
-
##
|
7
|
+
## Unreleased
|
8
|
+
|
9
|
+
## [0.7.0] - 2022-02-25
|
10
|
+
### Added
|
11
|
+
- Lambda definitions can now be failed with custom error messages
|
12
|
+
- Compatibility with Ruby 3.0
|
13
|
+
### Fixed
|
14
|
+
- In some cases errors from nested `Keys` definitions inside `Or` definitions got lost when listing the validation errors via the `error_hash` method on the conform result object.
|
15
|
+
### Changed
|
16
|
+
- When no sub-definition of an `Or` conforms, then only the errors of the last definition of the `Or` are collected. Previously the errors of all sub-definitions were collected.
|
17
|
+
- Translated error messages have been improved to be more suitable to be used as end user error messages
|
18
|
+
|
19
|
+
## [0.6.1] - 2021-12-14
|
8
20
|
### Fixed
|
9
21
|
- The `Keys` definition crashed with an error if the input was not a Hash
|
10
22
|
|
data/Gemfile.lock
CHANGED
@@ -1,31 +1,29 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
definition (0.
|
4
|
+
definition (0.7.0)
|
5
5
|
activesupport
|
6
6
|
i18n
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
|
-
activesupport (
|
11
|
+
activesupport (7.0.2.2)
|
12
12
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
13
13
|
i18n (>= 1.6, < 2)
|
14
14
|
minitest (>= 5.1)
|
15
15
|
tzinfo (~> 2.0)
|
16
|
-
zeitwerk (~> 2.3)
|
17
16
|
approvals (0.0.25)
|
18
17
|
nokogiri (~> 1.8)
|
19
18
|
thor (~> 1.0)
|
20
19
|
ast (2.4.2)
|
21
20
|
awesome_print (1.9.2)
|
22
|
-
benchmark-ips (2.
|
21
|
+
benchmark-ips (2.10.0)
|
23
22
|
coderay (1.1.3)
|
24
23
|
concurrent-ruby (1.1.9)
|
25
|
-
diff-lcs (1.
|
26
|
-
ffi (1.15.
|
27
|
-
|
28
|
-
formatador (0.3.0)
|
24
|
+
diff-lcs (1.5.0)
|
25
|
+
ffi (1.15.5)
|
26
|
+
formatador (1.1.0)
|
29
27
|
fuubar (2.5.1)
|
30
28
|
rspec-core (~> 3.0)
|
31
29
|
ruby-progressbar (~> 1.4)
|
@@ -43,66 +41,52 @@ GEM
|
|
43
41
|
guard (~> 2.1)
|
44
42
|
guard-compat (~> 1.1)
|
45
43
|
rspec (>= 2.99.0, < 4.0)
|
46
|
-
i18n (1.
|
44
|
+
i18n (1.10.0)
|
47
45
|
concurrent-ruby (~> 1.0)
|
48
|
-
jar-dependencies (0.4.1)
|
49
46
|
jaro_winkler (1.5.4)
|
50
|
-
|
51
|
-
listen (3.7.0)
|
47
|
+
listen (3.7.1)
|
52
48
|
rb-fsevent (~> 0.10, >= 0.10.3)
|
53
49
|
rb-inotify (~> 0.9, >= 0.9.10)
|
54
50
|
lumberjack (1.2.8)
|
55
51
|
method_source (1.0.0)
|
56
|
-
|
57
|
-
minitest (5.14.4)
|
52
|
+
minitest (5.15.0)
|
58
53
|
nenv (0.3.0)
|
59
|
-
nokogiri (1.
|
60
|
-
mini_portile2 (~> 2.6.1)
|
61
|
-
racc (~> 1.4)
|
62
|
-
nokogiri (1.12.5-java)
|
63
|
-
racc (~> 1.4)
|
64
|
-
nokogiri (1.12.5-x86_64-linux)
|
54
|
+
nokogiri (1.13.1-x86_64-linux)
|
65
55
|
racc (~> 1.4)
|
66
56
|
notiffany (0.1.3)
|
67
57
|
nenv (~> 0.1)
|
68
58
|
shellany (~> 0.0)
|
69
59
|
parallel (1.21.0)
|
70
|
-
parser (3.0.
|
60
|
+
parser (3.1.0.0)
|
71
61
|
ast (~> 2.4.1)
|
72
62
|
pry (0.14.1)
|
73
63
|
coderay (~> 1.1)
|
74
64
|
method_source (~> 1.0)
|
75
|
-
|
76
|
-
|
77
|
-
method_source (~> 1.0)
|
78
|
-
spoon (~> 0.0)
|
79
|
-
psych (4.0.2)
|
80
|
-
psych (4.0.2-java)
|
81
|
-
jar-dependencies (>= 0.1.7)
|
65
|
+
psych (4.0.3)
|
66
|
+
stringio
|
82
67
|
racc (1.6.0)
|
83
|
-
|
84
|
-
rainbow (3.0.0)
|
68
|
+
rainbow (3.1.1)
|
85
69
|
rake (13.0.6)
|
86
|
-
rb-fsevent (0.11.
|
70
|
+
rb-fsevent (0.11.1)
|
87
71
|
rb-inotify (0.10.1)
|
88
72
|
ffi (~> 1.0)
|
89
|
-
rspec (3.
|
90
|
-
rspec-core (~> 3.
|
91
|
-
rspec-expectations (~> 3.
|
92
|
-
rspec-mocks (~> 3.
|
93
|
-
rspec-core (3.
|
94
|
-
rspec-support (~> 3.
|
95
|
-
rspec-expectations (3.
|
73
|
+
rspec (3.11.0)
|
74
|
+
rspec-core (~> 3.11.0)
|
75
|
+
rspec-expectations (~> 3.11.0)
|
76
|
+
rspec-mocks (~> 3.11.0)
|
77
|
+
rspec-core (3.11.0)
|
78
|
+
rspec-support (~> 3.11.0)
|
79
|
+
rspec-expectations (3.11.0)
|
96
80
|
diff-lcs (>= 1.2.0, < 2.0)
|
97
|
-
rspec-support (~> 3.
|
81
|
+
rspec-support (~> 3.11.0)
|
98
82
|
rspec-its (1.3.0)
|
99
83
|
rspec-core (>= 3.0.0)
|
100
84
|
rspec-expectations (>= 3.0.0)
|
101
|
-
rspec-mocks (3.
|
85
|
+
rspec-mocks (3.11.0)
|
102
86
|
diff-lcs (>= 1.2.0, < 2.0)
|
103
|
-
rspec-support (~> 3.
|
104
|
-
rspec-support (3.
|
105
|
-
rspec_junit_formatter (0.
|
87
|
+
rspec-support (~> 3.11.0)
|
88
|
+
rspec-support (3.11.0)
|
89
|
+
rspec_junit_formatter (0.5.1)
|
106
90
|
rspec-core (>= 2, < 4, != 2.12.0)
|
107
91
|
rubocop (0.66.0)
|
108
92
|
jaro_winkler (~> 1.5.1)
|
@@ -117,18 +101,15 @@ GEM
|
|
117
101
|
rubocop_runner (2.2.0)
|
118
102
|
ruby-progressbar (1.11.0)
|
119
103
|
shellany (0.0.1)
|
120
|
-
|
121
|
-
|
122
|
-
thor (1.1.0)
|
104
|
+
stringio (3.0.1)
|
105
|
+
thor (1.2.1)
|
123
106
|
timecop (0.9.4)
|
124
107
|
tzinfo (2.0.4)
|
125
108
|
concurrent-ruby (~> 1.0)
|
126
109
|
unicode-display_width (1.5.0)
|
127
|
-
zeitwerk (2.5.1)
|
128
110
|
|
129
111
|
PLATFORMS
|
130
112
|
ruby
|
131
|
-
universal-java-11
|
132
113
|
x86_64-linux
|
133
114
|
|
134
115
|
DEPENDENCIES
|
@@ -150,4 +131,4 @@ DEPENDENCIES
|
|
150
131
|
timecop
|
151
132
|
|
152
133
|
BUNDLED WITH
|
153
|
-
2.
|
134
|
+
2.3.7
|
data/README.md
CHANGED
@@ -255,6 +255,24 @@ either be the original value or any transformed version of it. By not calling
|
|
255
255
|
The first argument of `Definition.Lambda` is a name you can give this definition.
|
256
256
|
It will only be used in the error message to make it more readable.
|
257
257
|
|
258
|
+
If you want to provide detailed custom error messages you can use `fail_with`:
|
259
|
+
|
260
|
+
```ruby
|
261
|
+
Definition.Lambda(:password) do |value|
|
262
|
+
if !value.match(/[a-z]+/)
|
263
|
+
fail_with("must contain at least one lower case letter")
|
264
|
+
elsif !value.match(/[A-Z]+/)
|
265
|
+
fail_with("must contain at least one upper case letter")
|
266
|
+
elsif !value.match(/\d+/)
|
267
|
+
fail_with("must contain at least one digit")
|
268
|
+
elsif value.size < 6 || value.size > 50
|
269
|
+
fail_with("must be between 6 and 50 characters long")
|
270
|
+
else
|
271
|
+
conform_with(value)
|
272
|
+
end
|
273
|
+
end
|
274
|
+
```
|
275
|
+
|
258
276
|
### Composing Definitions
|
259
277
|
|
260
278
|
Definitions are reusable and can be easily composed:
|
data/config/locales/en.yml
CHANGED
@@ -1,23 +1,22 @@
|
|
1
1
|
en:
|
2
2
|
definition:
|
3
|
-
max_size: "Value is bigger
|
4
|
-
min_size: "Value is smaller
|
5
|
-
greater_then: "Value must be greater
|
6
|
-
greater_then_equal: "Value must be greater or
|
7
|
-
less_then: "Value must be less
|
8
|
-
less_then_equal: "Value must be less or
|
3
|
+
max_size: "Value is bigger than %{max_size}"
|
4
|
+
min_size: "Value is smaller than %{min_size}"
|
5
|
+
greater_then: "Value must be greater than %{min_value}"
|
6
|
+
greater_then_equal: "Value must be greater or equal to %{min_value}"
|
7
|
+
less_then: "Value must be less than %{max_value}"
|
8
|
+
less_then_equal: "Value must be less or equal to %{max_value}"
|
9
9
|
equal: "Value must be equal to '%{expected_value}'"
|
10
10
|
empty: "Value must be empty"
|
11
11
|
non_empty: "Value must not be empty"
|
12
12
|
nil: "Value must be nil"
|
13
|
+
each: "Is not an Array"
|
14
|
+
include: "Does not include %{value}"
|
13
15
|
type: "Value is of wrong type, needs to be a %{class}"
|
14
16
|
enum: "Value is not one of: %{allowed_values}"
|
15
|
-
each: "Not all values are valid"
|
16
|
-
and: "Not all definitions conform"
|
17
|
-
or: "None of the definitions conform"
|
18
17
|
non_empty_string: "Value must be a non empty string"
|
19
|
-
regex: "Value
|
18
|
+
regex: "Value does not match regex %{regex}"
|
20
19
|
keys:
|
21
|
-
has_extra_key: "
|
22
|
-
has_missing_key: "
|
23
|
-
not_a_hash: "Is not a Hash"
|
20
|
+
has_extra_key: "Is unexpected"
|
21
|
+
has_missing_key: "Is missing"
|
22
|
+
not_a_hash: "Is not a Hash"
|
@@ -4,16 +4,18 @@ require "i18n"
|
|
4
4
|
|
5
5
|
module Definition
|
6
6
|
class ConformError
|
7
|
-
def initialize(definition, message, sub_errors: [],
|
7
|
+
def initialize(definition, message, sub_errors: [], **options)
|
8
8
|
self.definition = definition
|
9
9
|
self.message = message
|
10
10
|
self.sub_errors = sub_errors
|
11
|
-
self.i18n_key = i18n_key
|
11
|
+
self.i18n_key = options.fetch(:i18n_key, definition.name)
|
12
|
+
self.i18n_context = options.fetch(:i18n_context, {})
|
13
|
+
self.translated_error = options.fetch(:translated_message, nil)
|
12
14
|
assign_parents
|
13
15
|
end
|
14
16
|
|
15
|
-
attr_accessor :definition, :sub_errors, :parent, :i18n_key
|
16
|
-
attr_writer :message
|
17
|
+
attr_accessor :definition, :sub_errors, :parent, :i18n_key, :i18n_context
|
18
|
+
attr_writer :message, :translated_error
|
17
19
|
|
18
20
|
def message
|
19
21
|
if sub_errors.empty?
|
@@ -50,10 +52,8 @@ module Definition
|
|
50
52
|
sub_errors.map(&:leaf_errors).flatten
|
51
53
|
end
|
52
54
|
|
53
|
-
def translated_error(namespace = "definition"
|
54
|
-
|
55
|
-
vars[:key] = key if respond_to?(:key)
|
56
|
-
::I18n.t("#{namespace}.#{i18n_key}", definition.context.merge!(vars))
|
55
|
+
def translated_error(namespace = "definition")
|
56
|
+
@translated_error ||= definition.error_renderer.new(self, i18n_namespace: namespace).translated_error
|
57
57
|
end
|
58
58
|
|
59
59
|
private
|
data/lib/definition/dsl.rb
CHANGED
@@ -41,11 +41,9 @@ module Definition
|
|
41
41
|
"a primitive that has a coercion function defined")
|
42
42
|
end
|
43
43
|
Types::Type.new(:type, klass) do |value|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
value
|
48
|
-
end
|
44
|
+
method(klass.name).call(value)
|
45
|
+
rescue ArgumentError
|
46
|
+
value
|
49
47
|
end
|
50
48
|
end
|
51
49
|
|
@@ -4,9 +4,9 @@ require "definition/conform_error"
|
|
4
4
|
|
5
5
|
module Definition
|
6
6
|
class KeyConformError < ConformError
|
7
|
-
def initialize(definition, message, key:, sub_errors: [],
|
7
|
+
def initialize(definition, message, key:, sub_errors: [], **options)
|
8
8
|
self.key = key
|
9
|
-
super(definition, message, sub_errors: sub_errors,
|
9
|
+
super(definition, message, sub_errors: sub_errors, **options)
|
10
10
|
end
|
11
11
|
|
12
12
|
attr_accessor :key
|
data/lib/definition/types/and.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "definition/types/base"
|
4
|
+
require "definition/types/error_renderers/leaf"
|
4
5
|
|
5
6
|
module Definition
|
6
7
|
module Types
|
@@ -23,6 +24,10 @@ module Definition
|
|
23
24
|
Conformer.new(self).conform(value)
|
24
25
|
end
|
25
26
|
|
27
|
+
def error_renderer
|
28
|
+
ErrorRenderers::Leaf
|
29
|
+
end
|
30
|
+
|
26
31
|
class Conformer
|
27
32
|
def initialize(definition)
|
28
33
|
self.definition = definition
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "definition/conform_result"
|
4
4
|
require "definition/conform_error"
|
5
|
+
require "definition/types/error_renderers/standard"
|
5
6
|
|
6
7
|
module Definition
|
7
8
|
module Types
|
@@ -23,6 +24,10 @@ module Definition
|
|
23
24
|
def conform(_value)
|
24
25
|
raise NotImplementedError
|
25
26
|
end
|
27
|
+
|
28
|
+
def error_renderer
|
29
|
+
ErrorRenderers::Standard
|
30
|
+
end
|
26
31
|
end
|
27
32
|
end
|
28
33
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "definition/types/base"
|
4
|
+
require "definition/types/error_renderers/leaf"
|
4
5
|
|
5
6
|
module Definition
|
6
7
|
module Types
|
@@ -16,6 +17,10 @@ module Definition
|
|
16
17
|
Conformer.new(self).conform(value)
|
17
18
|
end
|
18
19
|
|
20
|
+
def error_renderer
|
21
|
+
ErrorRenderers::Leaf
|
22
|
+
end
|
23
|
+
|
19
24
|
class Conformer
|
20
25
|
def initialize(definition)
|
21
26
|
self.definition = definition
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "definition/types/error_renderers/standard"
|
4
|
+
|
5
|
+
module Definition
|
6
|
+
module Types
|
7
|
+
module ErrorRenderers
|
8
|
+
class Lambda < Standard
|
9
|
+
def default
|
10
|
+
"Did not pass test for '#{conform_error.definition.name}'"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "definition/types/error_renderers/standard"
|
4
|
+
|
5
|
+
module Definition
|
6
|
+
module Types
|
7
|
+
module ErrorRenderers
|
8
|
+
class Leaf < Standard
|
9
|
+
def translated_error(_namespace = "definition")
|
10
|
+
# When there are no sub errors, proceeding gets us into an infinite loop.
|
11
|
+
return i18n_error if conform_error.sub_errors.empty?
|
12
|
+
|
13
|
+
conform_error.leaf_errors.map(&:translated_error).join(", ")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Definition
|
4
|
+
module Types
|
5
|
+
module ErrorRenderers
|
6
|
+
class Standard
|
7
|
+
def initialize(conform_error, i18n_namespace:)
|
8
|
+
self.conform_error = conform_error
|
9
|
+
self.i18n_namespace = i18n_namespace
|
10
|
+
end
|
11
|
+
|
12
|
+
def translated_error
|
13
|
+
i18n_error
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def i18n_error
|
19
|
+
::I18n.t("#{i18n_namespace}.#{conform_error.i18n_key}",
|
20
|
+
**i18n_vars)
|
21
|
+
end
|
22
|
+
|
23
|
+
def i18n_vars
|
24
|
+
conform_error.definition.context.merge(
|
25
|
+
conform_error.i18n_context
|
26
|
+
).tap do |vars|
|
27
|
+
vars[:default] = default if default
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def default
|
32
|
+
nil
|
33
|
+
end
|
34
|
+
|
35
|
+
attr_accessor :conform_error, :i18n_namespace
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -38,7 +38,8 @@ module Definition
|
|
38
38
|
definition.required_items.map do |item|
|
39
39
|
next if value.include?(item)
|
40
40
|
|
41
|
-
KeyConformError.new(definition, "#{definition.name} does not include #{item.inspect}",
|
41
|
+
KeyConformError.new(definition, "#{definition.name} does not include #{item.inspect}",
|
42
|
+
key: item, i18n_context: { value: item.inspect })
|
42
43
|
end.compact
|
43
44
|
end
|
44
45
|
|
@@ -1,34 +1,65 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "definition/types/base"
|
4
|
+
require "definition/types/error_renderers/lambda"
|
4
5
|
|
5
6
|
module Definition
|
6
7
|
module Types
|
7
8
|
class Lambda < Base
|
8
|
-
|
9
|
-
def conform_with(value)
|
10
|
-
ConformResult.new(value)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
include Dsl
|
9
|
+
attr_accessor :conformity_test_lambda
|
14
10
|
|
15
|
-
def initialize(name, context: {}, &
|
16
|
-
self.
|
11
|
+
def initialize(name, context: {}, &conformity_test_lambda)
|
12
|
+
self.conformity_test_lambda = conformity_test_lambda
|
17
13
|
super(name, context: context)
|
18
14
|
end
|
19
15
|
|
20
16
|
def conform(value)
|
21
|
-
|
22
|
-
|
17
|
+
Conformer.new(self).conform(value)
|
18
|
+
end
|
23
19
|
|
24
|
-
|
25
|
-
|
26
|
-
])
|
20
|
+
def error_renderer
|
21
|
+
ErrorRenderers::Lambda
|
27
22
|
end
|
28
23
|
|
29
|
-
|
24
|
+
class Conformer
|
25
|
+
module Dsl
|
26
|
+
def conform_with(value)
|
27
|
+
ConformResult.new(value)
|
28
|
+
end
|
29
|
+
|
30
|
+
def fail_with(error_message)
|
31
|
+
self.error_message = error_message
|
32
|
+
end
|
33
|
+
end
|
34
|
+
include Dsl
|
35
|
+
|
36
|
+
def initialize(definition)
|
37
|
+
self.definition = definition
|
38
|
+
end
|
39
|
+
|
40
|
+
def conform(value)
|
41
|
+
lambda_result = instance_exec(value, &definition.conformity_test_lambda)
|
42
|
+
return lambda_result if lambda_result.is_a?(ConformResult)
|
30
43
|
|
31
|
-
|
44
|
+
failure_result_with(value, error_message)
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
attr_accessor :definition, :error_message
|
50
|
+
|
51
|
+
def standard_error_message
|
52
|
+
"Did not pass test for #{definition.name}"
|
53
|
+
end
|
54
|
+
|
55
|
+
def failure_result_with(value, error_message)
|
56
|
+
ConformResult.new(value, errors: [
|
57
|
+
ConformError.new(definition,
|
58
|
+
standard_error_message,
|
59
|
+
translated_message: error_message)
|
60
|
+
])
|
61
|
+
end
|
62
|
+
end
|
32
63
|
end
|
33
64
|
end
|
34
65
|
end
|
data/lib/definition/types/or.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "definition/types/base"
|
4
|
+
require "definition/types/error_renderers/leaf"
|
4
5
|
|
5
6
|
module Definition
|
6
7
|
module Types
|
@@ -23,6 +24,10 @@ module Definition
|
|
23
24
|
Conformer.new(self).conform(value)
|
24
25
|
end
|
25
26
|
|
27
|
+
def error_renderer
|
28
|
+
ErrorRenderers::Leaf
|
29
|
+
end
|
30
|
+
|
26
31
|
class Conformer
|
27
32
|
def initialize(definition)
|
28
33
|
self.definition = definition
|
@@ -34,7 +39,8 @@ module Definition
|
|
34
39
|
result
|
35
40
|
else
|
36
41
|
error = ConformError.new(definition,
|
37
|
-
"None of the definitions are valid for '#{definition.name}'"
|
42
|
+
"None of the definitions are valid for '#{definition.name}'."\
|
43
|
+
" Errors for last tested definition:",
|
38
44
|
sub_errors: result)
|
39
45
|
ConformResult.new(value, errors: [error])
|
40
46
|
end
|
@@ -48,7 +54,7 @@ module Definition
|
|
48
54
|
result = definition.conform(value)
|
49
55
|
return result if result.passed?
|
50
56
|
|
51
|
-
errors
|
57
|
+
errors = result.error_tree
|
52
58
|
end
|
53
59
|
|
54
60
|
errors.flatten
|
data/lib/definition/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: definition
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dominik Goltermann
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-02-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -286,6 +286,9 @@ files:
|
|
286
286
|
- lib/definition/types/and.rb
|
287
287
|
- lib/definition/types/base.rb
|
288
288
|
- lib/definition/types/each.rb
|
289
|
+
- lib/definition/types/error_renderers/lambda.rb
|
290
|
+
- lib/definition/types/error_renderers/leaf.rb
|
291
|
+
- lib/definition/types/error_renderers/standard.rb
|
289
292
|
- lib/definition/types/include.rb
|
290
293
|
- lib/definition/types/keys.rb
|
291
294
|
- lib/definition/types/lambda.rb
|