validate-rb 0.1.0.alpha.1 → 0.1.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/.travis.yml +6 -0
- data/Gemfile +7 -0
- data/README.md +4 -4
- data/Rakefile +6 -0
- data/bin/console +7 -0
- data/bin/setup +6 -0
- data/lib/validate/version.rb +1 -1
- data/lib/validate-rb.rb +3 -0
- data/lib/validate.rb +1 -75
- data/validate-rb.gemspec +30 -0
- metadata +21 -122
- data/LICENSE +0 -21
- data/lib/validate/arguments.rb +0 -93
- data/lib/validate/assertions.rb +0 -27
- data/lib/validate/ast.rb +0 -381
- data/lib/validate/compare.rb +0 -34
- data/lib/validate/constraint.rb +0 -217
- data/lib/validate/constraints/validation_context.rb +0 -167
- data/lib/validate/constraints.rb +0 -337
- data/lib/validate/errors.rb +0 -40
- data/lib/validate/helpers.rb +0 -11
- data/lib/validate/scope.rb +0 -48
- data/lib/validate/validators/dsl.rb +0 -44
- data/lib/validate/validators.rb +0 -7
@@ -1,167 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Validate
|
4
|
-
module Constraints
|
5
|
-
class ValidationContext
|
6
|
-
def self.none
|
7
|
-
@none ||= None.new
|
8
|
-
end
|
9
|
-
|
10
|
-
def self.root(value, violations = [])
|
11
|
-
new(value, Path.new, violations)
|
12
|
-
end
|
13
|
-
|
14
|
-
attr_reader :value
|
15
|
-
|
16
|
-
def initialize(value, path = Path.new, violations = [])
|
17
|
-
@value = value
|
18
|
-
@path = path
|
19
|
-
@violations = violations
|
20
|
-
@keys = Hash.new do |hash, key|
|
21
|
-
unless @value.respond_to?(:[]) || @value.respond_to_missing?(:[])
|
22
|
-
raise Error::KeyError,
|
23
|
-
"#{key.inspect}: value doesn't respond to :[]"
|
24
|
-
end
|
25
|
-
begin
|
26
|
-
hash[key] = child_context(@value[key], KeyPath.new(key))
|
27
|
-
rescue => e
|
28
|
-
raise Error::KeyError,
|
29
|
-
"#{key.inspect}: #{e.message}",
|
30
|
-
cause: e
|
31
|
-
end
|
32
|
-
end
|
33
|
-
@attrs = Hash.new do |hash, attr|
|
34
|
-
unless @value.respond_to?(attr) || @value.respond_to_missing?(attr)
|
35
|
-
raise Error::NameError,
|
36
|
-
"#{attr.inspect}: value doesn't respond to #{attr.inspect}"
|
37
|
-
end
|
38
|
-
hash[attr] = child_context(@value.send(attr), AttrPath.new(attr))
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def [](key)
|
43
|
-
@keys[key]
|
44
|
-
end
|
45
|
-
|
46
|
-
def attr(name)
|
47
|
-
@attrs[name]
|
48
|
-
end
|
49
|
-
|
50
|
-
def add_violation(constraint)
|
51
|
-
@violations << create_violation(constraint)
|
52
|
-
self
|
53
|
-
end
|
54
|
-
|
55
|
-
def clear_violations
|
56
|
-
@violations.clear
|
57
|
-
self
|
58
|
-
end
|
59
|
-
|
60
|
-
def has_violations?
|
61
|
-
!@violations.empty?
|
62
|
-
end
|
63
|
-
|
64
|
-
def to_err
|
65
|
-
Error::ConstraintViolationError.new(@violations.freeze)
|
66
|
-
end
|
67
|
-
|
68
|
-
private
|
69
|
-
|
70
|
-
def create_violation(constraint)
|
71
|
-
Constraint::Violation.new(@value, @path, constraint)
|
72
|
-
end
|
73
|
-
|
74
|
-
def child_context(value, path)
|
75
|
-
ValidationContext.new(value, @path.child(path), @violations)
|
76
|
-
end
|
77
|
-
|
78
|
-
class Path
|
79
|
-
extend Forwardable
|
80
|
-
|
81
|
-
def_delegators(:@paths, :empty?, :length, :size, :each)
|
82
|
-
|
83
|
-
include Enumerable
|
84
|
-
|
85
|
-
def initialize(paths = [])
|
86
|
-
@paths = paths
|
87
|
-
end
|
88
|
-
|
89
|
-
def child(path)
|
90
|
-
Path.new(@paths.dup << path)
|
91
|
-
end
|
92
|
-
|
93
|
-
def to_s
|
94
|
-
return '.' if @paths.empty?
|
95
|
-
|
96
|
-
@paths.join
|
97
|
-
end
|
98
|
-
|
99
|
-
def at(index)
|
100
|
-
raise Error::IndexError if index.negative?
|
101
|
-
|
102
|
-
return nil if index.zero?
|
103
|
-
@paths.fetch(index - 1)
|
104
|
-
end
|
105
|
-
|
106
|
-
def inspect
|
107
|
-
return "#<#{self.class.name} <root>>" if @paths.empty?
|
108
|
-
|
109
|
-
"#<#{self.class.name} #{to_s}>"
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
class KeyPath
|
114
|
-
def initialize(key)
|
115
|
-
@key = key
|
116
|
-
end
|
117
|
-
|
118
|
-
def to_s
|
119
|
-
"[#{@key.inspect}]"
|
120
|
-
end
|
121
|
-
|
122
|
-
def inspect
|
123
|
-
"#<#{self.class.name} #{@key.inspect}>"
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
class AttrPath
|
128
|
-
def initialize(attr)
|
129
|
-
@attr = attr
|
130
|
-
end
|
131
|
-
|
132
|
-
def to_s
|
133
|
-
".#{@attr}"
|
134
|
-
end
|
135
|
-
|
136
|
-
def inspect
|
137
|
-
"#<#{self.class.name} #{@attr.inspect}>"
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
class None < ValidationContext
|
142
|
-
def initialize
|
143
|
-
end
|
144
|
-
|
145
|
-
def [](_)
|
146
|
-
self
|
147
|
-
end
|
148
|
-
|
149
|
-
def attr(_)
|
150
|
-
self
|
151
|
-
end
|
152
|
-
|
153
|
-
def add_violation(_)
|
154
|
-
self
|
155
|
-
end
|
156
|
-
|
157
|
-
def clear_violations
|
158
|
-
self
|
159
|
-
end
|
160
|
-
|
161
|
-
def has_violations?
|
162
|
-
false
|
163
|
-
end
|
164
|
-
end
|
165
|
-
end
|
166
|
-
end
|
167
|
-
end
|
data/lib/validate/constraints.rb
DELETED
@@ -1,337 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Validate
|
4
|
-
module Constraints
|
5
|
-
include Validate::Arguments
|
6
|
-
|
7
|
-
@reserved_names = Hash[%i[define validation_context].map { |n| [n, n] }]
|
8
|
-
|
9
|
-
arg(:name) do
|
10
|
-
not_blank(message: 'constraint name must not be blank')
|
11
|
-
is_a(Symbol, message: 'constraint name must be a Symbol')
|
12
|
-
end
|
13
|
-
arg(:body) do
|
14
|
-
not_nil(message: 'constraint body is required')
|
15
|
-
end
|
16
|
-
def self.define(name, **defaults, &body)
|
17
|
-
if @reserved_names.include?(name)
|
18
|
-
raise Error::ArgumentError,
|
19
|
-
"#{name} is already defined"
|
20
|
-
end
|
21
|
-
|
22
|
-
@reserved_names[name] = name
|
23
|
-
constraint_class = Constraint.create_class(name, defaults, &body)
|
24
|
-
Constraints.const_set(Helpers.camelize(name), constraint_class)
|
25
|
-
define_method(name, &constraint_class.method(:new))
|
26
|
-
module_function(name)
|
27
|
-
end
|
28
|
-
|
29
|
-
define(:not_nil, message: 'not be nil') do
|
30
|
-
evaluate { |value| fail if value.nil? }
|
31
|
-
end
|
32
|
-
|
33
|
-
define(:not_blank, message: 'not be blank') do
|
34
|
-
evaluate do |value|
|
35
|
-
fail if value.nil? || !value.respond_to?(:empty?) || value.empty?
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
define(:not_empty, message: 'not be empty') do
|
40
|
-
evaluate { |value| fail if value&.empty? }
|
41
|
-
end
|
42
|
-
|
43
|
-
define(:is_a, message: 'be a %{constraint.klass}') do
|
44
|
-
option(:klass) do
|
45
|
-
not_nil(message: 'klass is required')
|
46
|
-
end
|
47
|
-
|
48
|
-
initialize { |klass| { klass: klass } }
|
49
|
-
evaluate do |value|
|
50
|
-
pass if value.nil?
|
51
|
-
|
52
|
-
klass = options[:klass]
|
53
|
-
fail unless klass === value
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
define(:respond_to, message: 'respond to %{constraint.method_name.inspect}') do
|
58
|
-
option(:method_name) do
|
59
|
-
not_blank(message: 'method_name is required')
|
60
|
-
is_a(Symbol, message: 'method_name must be a Symbol')
|
61
|
-
end
|
62
|
-
|
63
|
-
initialize do |method_name|
|
64
|
-
method_name.nil? ? {} : { method_name: method_name }
|
65
|
-
end
|
66
|
-
evaluate do |instance|
|
67
|
-
pass if instance.nil?
|
68
|
-
fail unless instance.respond_to?(options[:method_name])
|
69
|
-
end
|
70
|
-
key { "respond_to_#{options[:method_name]}" }
|
71
|
-
end
|
72
|
-
|
73
|
-
define(:length, message: 'have length of %{constraint.describe_length}') do
|
74
|
-
option(:min) { respond_to(:>, message: 'min must respond to :>') }
|
75
|
-
option(:max) { respond_to(:<, message: 'max must respond to :<') }
|
76
|
-
|
77
|
-
initialize do |range = nil|
|
78
|
-
case range
|
79
|
-
when ::Range
|
80
|
-
{ min: range.min, max: range.max }
|
81
|
-
else
|
82
|
-
{ min: range, max: range }
|
83
|
-
end
|
84
|
-
end
|
85
|
-
evaluate do |value|
|
86
|
-
pass if value.nil?
|
87
|
-
fail unless value.respond_to?(:length)
|
88
|
-
|
89
|
-
length = value.length
|
90
|
-
fail if (options[:min]&.> length) || (options[:max]&.< length)
|
91
|
-
end
|
92
|
-
|
93
|
-
def describe_length
|
94
|
-
if options[:max] == options[:min]
|
95
|
-
options[:max].to_s
|
96
|
-
elsif options[:max].nil?
|
97
|
-
"at least #{options[:min]}"
|
98
|
-
elsif options[:min].nil?
|
99
|
-
"at most #{options[:max]}"
|
100
|
-
else
|
101
|
-
"at least #{options[:min]} and at most #{options[:max]}"
|
102
|
-
end
|
103
|
-
end
|
104
|
-
key { "length_over_#{options[:min]}_under_#{options[:max]}" }
|
105
|
-
end
|
106
|
-
|
107
|
-
define(:one_of, message: 'be %{constraint.describe_presence}') do
|
108
|
-
option(:values) do
|
109
|
-
respond_to(:include?, message: 'values must respond to :include?')
|
110
|
-
end
|
111
|
-
|
112
|
-
initialize do |*values|
|
113
|
-
if values.one? && values.first.respond_to?(:include?)
|
114
|
-
{ values: values.first }
|
115
|
-
else
|
116
|
-
{ values: values }
|
117
|
-
end
|
118
|
-
end
|
119
|
-
evaluate do |value|
|
120
|
-
pass if value.nil?
|
121
|
-
|
122
|
-
values = options[:values]
|
123
|
-
pass if values.respond_to?(:cover?) && values.cover?(value)
|
124
|
-
fail unless values.include?(value)
|
125
|
-
end
|
126
|
-
|
127
|
-
def describe_presence
|
128
|
-
case options[:values]
|
129
|
-
when ::Hash
|
130
|
-
"one of #{options[:values].keys}"
|
131
|
-
when ::Range
|
132
|
-
"covered by #{options[:values]}"
|
133
|
-
else
|
134
|
-
"one of #{options[:values]}"
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
define(:validate, message: 'pass validation') do
|
140
|
-
option(:using) do
|
141
|
-
not_nil(message: 'using is required')
|
142
|
-
is_a(Proc, message: 'using must be a Proc')
|
143
|
-
end
|
144
|
-
|
145
|
-
initialize { |&validate_block| { using: validate_block } }
|
146
|
-
evaluate do |value|
|
147
|
-
pass if value.nil?
|
148
|
-
fail unless instance_exec(value, &options[:using])
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
define(:attr, message: 'have attribute %{constraint.attribute}') do
|
153
|
-
option(:attribute) do
|
154
|
-
not_nil(message: 'attribute is required')
|
155
|
-
is_a(Symbol, message: 'attribute must be a Symbol')
|
156
|
-
end
|
157
|
-
option(:constraints) do
|
158
|
-
is_a(AST::DefinitionContext, message: 'constraints must be a DefinitionContext')
|
159
|
-
end
|
160
|
-
|
161
|
-
initialize do |attribute, &block|
|
162
|
-
{ attribute: attribute,
|
163
|
-
constraints: block && AST::DefinitionContext.create(&block) }
|
164
|
-
end
|
165
|
-
evaluate do |value, ctx|
|
166
|
-
pass if value.nil?
|
167
|
-
|
168
|
-
attribute = options[:attribute]
|
169
|
-
begin
|
170
|
-
options[:constraints].evaluate(ctx.attr(attribute))
|
171
|
-
rescue NameError
|
172
|
-
fail
|
173
|
-
end
|
174
|
-
end
|
175
|
-
key { "attr_#{options[:attribute]}" }
|
176
|
-
end
|
177
|
-
|
178
|
-
define(:key, message: 'have key %{constraint.key.inspect}') do
|
179
|
-
option(:key) do
|
180
|
-
not_nil(message: 'key is required')
|
181
|
-
end
|
182
|
-
option(:constraints) do
|
183
|
-
is_a(AST::DefinitionContext, message: 'constraints must be a DefinitionContext')
|
184
|
-
end
|
185
|
-
|
186
|
-
initialize do |key, &block|
|
187
|
-
{ key: key,
|
188
|
-
constraints: block && AST::DefinitionContext.create(&block) }
|
189
|
-
end
|
190
|
-
|
191
|
-
evaluate do |instance, ctx|
|
192
|
-
pass if instance.nil?
|
193
|
-
fail unless instance.respond_to?(:[])
|
194
|
-
|
195
|
-
key = options[:key]
|
196
|
-
begin
|
197
|
-
options[:constraints]&.evaluate(ctx[key])
|
198
|
-
rescue KeyError
|
199
|
-
fail
|
200
|
-
end
|
201
|
-
end
|
202
|
-
key { "key_#{options[:key]}" }
|
203
|
-
end
|
204
|
-
|
205
|
-
define(:min, message: 'be at least %{constraint.min}') do
|
206
|
-
option(:min) do
|
207
|
-
not_nil(message: 'min is required')
|
208
|
-
respond_to(:>, message: 'min must respond to :>')
|
209
|
-
end
|
210
|
-
|
211
|
-
initialize do |min = nil|
|
212
|
-
min.nil? ? {} : { min: min }
|
213
|
-
end
|
214
|
-
evaluate do |value|
|
215
|
-
pass if value.nil?
|
216
|
-
fail if options[:min] > value
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
define(:max, message: 'be at most %{constraint.max}') do
|
221
|
-
option(:max) do
|
222
|
-
not_nil(message: 'max is required')
|
223
|
-
respond_to(:<, message: 'max must respond to :<')
|
224
|
-
end
|
225
|
-
|
226
|
-
initialize do |max = nil|
|
227
|
-
max.nil? ? {} : { max: max }
|
228
|
-
end
|
229
|
-
evaluate do |value|
|
230
|
-
pass if value.nil?
|
231
|
-
fail if options[:max] < value
|
232
|
-
end
|
233
|
-
end
|
234
|
-
|
235
|
-
define(:equal, message: 'be equal to %{constraint.equal}') do
|
236
|
-
option(:equal) do
|
237
|
-
not_nil(message: 'equal is required')
|
238
|
-
respond_to(:==, message: 'equal must respond to :==')
|
239
|
-
end
|
240
|
-
|
241
|
-
initialize do |equal = nil|
|
242
|
-
equal.nil? ? {} : { equal: equal }
|
243
|
-
end
|
244
|
-
evaluate do |value|
|
245
|
-
pass if value.nil?
|
246
|
-
fail unless options[:equal] == value
|
247
|
-
end
|
248
|
-
end
|
249
|
-
|
250
|
-
define(:match, message: 'match %{constraint.regexp}') do
|
251
|
-
option(:regexp) do
|
252
|
-
not_nil(message: 'regexp is required')
|
253
|
-
respond_to(:=~, message: 'regexp must respond to :=~')
|
254
|
-
end
|
255
|
-
|
256
|
-
initialize do |regexp = nil|
|
257
|
-
regexp.nil? ? {} : { regexp: regexp }
|
258
|
-
end
|
259
|
-
evaluate do |value|
|
260
|
-
pass if value.nil?
|
261
|
-
fail unless value.is_a?(String) && options[:regexp] =~ value
|
262
|
-
end
|
263
|
-
end
|
264
|
-
|
265
|
-
define(:valid, message: 'be valid %{constraint.validator || value.class}') do
|
266
|
-
option(:validator, default: nil)
|
267
|
-
|
268
|
-
initialize do |validator = nil|
|
269
|
-
validator.nil? ? {} : { validator: validator }
|
270
|
-
end
|
271
|
-
evaluate do |value, ctx|
|
272
|
-
pass if value.nil?
|
273
|
-
|
274
|
-
Scope.current
|
275
|
-
.validator(options[:validator] || value.class)
|
276
|
-
.validate(ctx)
|
277
|
-
end
|
278
|
-
key { options[:validator] && "valid_#{options[:validator]}" || 'valid' }
|
279
|
-
end
|
280
|
-
|
281
|
-
define(:each_value, message: 'have values') do
|
282
|
-
option(:constraints) do
|
283
|
-
not_nil(message: 'constraints are required')
|
284
|
-
is_a(AST::DefinitionContext, message: 'constraints must be a DefinitionContext')
|
285
|
-
end
|
286
|
-
|
287
|
-
initialize do |&block|
|
288
|
-
return {} if block.nil?
|
289
|
-
|
290
|
-
{ constraints: AST::DefinitionContext.create(&block) }
|
291
|
-
end
|
292
|
-
evaluate do |collection, ctx|
|
293
|
-
pass if collection.nil?
|
294
|
-
fail unless collection.respond_to?(:each)
|
295
|
-
|
296
|
-
constraints = options[:constraints]
|
297
|
-
case collection
|
298
|
-
when ::Hash
|
299
|
-
collection.each do |key, value|
|
300
|
-
constraints.evaluate(ctx[key])
|
301
|
-
end
|
302
|
-
else
|
303
|
-
i = 0
|
304
|
-
collection.each do |value|
|
305
|
-
constraints.evaluate(ctx[i])
|
306
|
-
i += 1
|
307
|
-
end
|
308
|
-
end
|
309
|
-
end
|
310
|
-
end
|
311
|
-
|
312
|
-
define(
|
313
|
-
:unique,
|
314
|
-
message: 'have unique %{constraint.describe_unique_attribute}'
|
315
|
-
) do
|
316
|
-
option(:attribute, default: nil) do
|
317
|
-
is_a(Symbol, message: 'attribute %{value.inspect} must be a Symbol')
|
318
|
-
end
|
319
|
-
|
320
|
-
initialize do |attribute = nil|
|
321
|
-
attribute.nil? ? {} : { attribute: attribute }
|
322
|
-
end
|
323
|
-
evaluate do |value|
|
324
|
-
pass if value.nil?
|
325
|
-
fail unless value.respond_to?(:uniq) && value.respond_to?(:size)
|
326
|
-
fail unless value.size == value.uniq(&options[:attribute]).size
|
327
|
-
end
|
328
|
-
key do
|
329
|
-
options[:attribute] && "unique_#{options[:attribute]}" || 'unique'
|
330
|
-
end
|
331
|
-
|
332
|
-
def describe_unique_attribute
|
333
|
-
options[:attribute] || 'values'
|
334
|
-
end
|
335
|
-
end
|
336
|
-
end
|
337
|
-
end
|
data/lib/validate/errors.rb
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Validate
|
4
|
-
module Error
|
5
|
-
class StandardError < ::StandardError
|
6
|
-
include Error
|
7
|
-
end
|
8
|
-
|
9
|
-
class ArgumentError < ::ArgumentError
|
10
|
-
include Error
|
11
|
-
end
|
12
|
-
|
13
|
-
class KeyError < ::KeyError
|
14
|
-
include Error
|
15
|
-
end
|
16
|
-
|
17
|
-
class IndexError < ::IndexError
|
18
|
-
include Error
|
19
|
-
end
|
20
|
-
|
21
|
-
class ValidationRuleError < StandardError
|
22
|
-
end
|
23
|
-
|
24
|
-
class ConstraintViolationError < StandardError
|
25
|
-
attr_reader :violations
|
26
|
-
|
27
|
-
def initialize(violations)
|
28
|
-
@violations = violations
|
29
|
-
super()
|
30
|
-
end
|
31
|
-
|
32
|
-
def message
|
33
|
-
@violations.group_by(&:path)
|
34
|
-
.transform_values { |violations| violations.map(&:message) }
|
35
|
-
.map { |path, messages| "#{path}: #{messages.join(' ')}" }
|
36
|
-
.join("\n")
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
data/lib/validate/helpers.rb
DELETED
data/lib/validate/scope.rb
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
# typed: strict
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
module Validate
|
5
|
-
class Scope
|
6
|
-
def self.current
|
7
|
-
@current ||= Scope.new
|
8
|
-
end
|
9
|
-
|
10
|
-
def initialize
|
11
|
-
@constraints = {}
|
12
|
-
@validators = {}
|
13
|
-
end
|
14
|
-
|
15
|
-
def register_validator(name, validator)
|
16
|
-
if @validators.include?(name)
|
17
|
-
raise Error::ArgumentError,
|
18
|
-
"duplicate validator :#{name}"
|
19
|
-
end
|
20
|
-
|
21
|
-
@validators[name] = validator
|
22
|
-
end
|
23
|
-
|
24
|
-
def validator?(name)
|
25
|
-
@validators.include?(name)
|
26
|
-
end
|
27
|
-
|
28
|
-
def validator(name)
|
29
|
-
validator_name.assert(name,
|
30
|
-
message: "invalid validator #{name.inspect}",
|
31
|
-
error_class: KeyError)
|
32
|
-
|
33
|
-
@validators.fetch(name) { name.validator }
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
def validator_name
|
39
|
-
@validator_name ||= Assertions.create(@validators) do |validators|
|
40
|
-
not_nil(message: 'name must not be nil')
|
41
|
-
(one_of(values: validators,
|
42
|
-
message: '%{value.inspect} must be an existing validator name') |
|
43
|
-
respond_to(:validator,
|
44
|
-
message: '%{value.inspect} must respond to :validator'))
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Validate
|
4
|
-
module Validators
|
5
|
-
module DSL
|
6
|
-
include Arguments
|
7
|
-
|
8
|
-
arg(:name) { is_a(Module) | (is_a(Symbol) & not_blank) }
|
9
|
-
def define(name, &body)
|
10
|
-
Scope.current.register_validator(name, create(&body))
|
11
|
-
end
|
12
|
-
|
13
|
-
def create(&block)
|
14
|
-
Validator.new(&block)
|
15
|
-
end
|
16
|
-
|
17
|
-
def none
|
18
|
-
@none ||= Validator::None.new
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
class Validator
|
23
|
-
def initialize(&block)
|
24
|
-
@constraints = AST::DefinitionContext.create(&block)
|
25
|
-
end
|
26
|
-
|
27
|
-
def validate(ctx)
|
28
|
-
@constraints.evaluate(ctx)
|
29
|
-
end
|
30
|
-
|
31
|
-
private
|
32
|
-
|
33
|
-
class None < Validator
|
34
|
-
NO_VIOLATIONS = [].freeze
|
35
|
-
|
36
|
-
def initialize; end
|
37
|
-
|
38
|
-
def validate(*args)
|
39
|
-
NO_VIOLATIONS
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|