validate 1.2.1 → 1.3
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.
- data/lib/validate/parser.rb +27 -3
- data/lib/validate/validations.rb +3 -2
- data/lib/validate/validator.rb +19 -4
- data/lib/validate/version.rb +1 -1
- data/spec/validate_spec.rb +63 -2
- metadata +2 -2
data/lib/validate/parser.rb
CHANGED
@@ -26,13 +26,24 @@ module Validate
|
|
26
26
|
end
|
27
27
|
|
28
28
|
|
29
|
+
# CompiledValidations is a struct that represents a set of compiled
|
30
|
+
# validations + options, eg. whether to allow extra keys.
|
31
|
+
#
|
32
|
+
class CompiledValidations < Struct.new(:validations, :allow_keys); end
|
33
|
+
|
34
|
+
|
29
35
|
class BlockParsingContext
|
30
36
|
|
31
37
|
def initialize
|
38
|
+
@allow_keys = :any
|
32
39
|
@validations = []
|
33
40
|
end
|
34
41
|
|
35
|
-
|
42
|
+
# Returns a CompiledValidations struct.
|
43
|
+
#
|
44
|
+
def validations
|
45
|
+
CompiledValidations.new(@validations, @allow_keys)
|
46
|
+
end
|
36
47
|
|
37
48
|
def method_missing(method, *args, &block)
|
38
49
|
raise NoMethodError.new("No method #{method} to call in the context of a validation block.") unless method.to_s =~ /^validates/
|
@@ -51,12 +62,12 @@ module Validate
|
|
51
62
|
|
52
63
|
# `when` is a special case, its syntax is as follows:
|
53
64
|
#
|
54
|
-
#
|
65
|
+
# run_when -> { ... } do
|
55
66
|
# # validations go here
|
56
67
|
# end
|
57
68
|
#
|
58
69
|
def run_when(condition, &block)
|
59
|
-
validations = Parser.parse(&block)
|
70
|
+
validations = Parser.parse(&block).validations
|
60
71
|
validations.map do |v|
|
61
72
|
v[:opts] ||= {}
|
62
73
|
v[:opts][:when] = condition
|
@@ -64,6 +75,19 @@ module Validate
|
|
64
75
|
end
|
65
76
|
@validations += validations
|
66
77
|
end
|
78
|
+
|
79
|
+
# `allow_keys` is another special case, which can be used like this:
|
80
|
+
#
|
81
|
+
# allow_keys :any
|
82
|
+
# allow_keys :valid
|
83
|
+
# allow_keys %w(one two three)
|
84
|
+
#
|
85
|
+
# Defaults to :any, if not specified.
|
86
|
+
#
|
87
|
+
def allow_keys(keys)
|
88
|
+
@allow_keys = keys
|
89
|
+
end
|
90
|
+
|
67
91
|
end
|
68
92
|
end
|
69
93
|
|
data/lib/validate/validations.rb
CHANGED
@@ -19,7 +19,8 @@ module Validate
|
|
19
19
|
#
|
20
20
|
fails_because_key 'failed to match a custom validation.'
|
21
21
|
def validates(obj, field, opts, validator)
|
22
|
-
|
22
|
+
args = [obj, field].first(opts[:with].arity)
|
23
|
+
true == obj[field].instance_exec(*args, &opts[:with])
|
23
24
|
end
|
24
25
|
|
25
26
|
# Validates that a field exists.
|
@@ -64,7 +65,7 @@ module Validate
|
|
64
65
|
#
|
65
66
|
# validates_value_of :field, is: 'something'
|
66
67
|
#
|
67
|
-
fails_because_key { "was not
|
68
|
+
fails_because_key { "was not #{opts[:is].inspect}." }
|
68
69
|
def validates_value_of(obj, field, opts, validator)
|
69
70
|
obj.include?(field) && obj[field] == opts[:is]
|
70
71
|
end
|
data/lib/validate/validator.rb
CHANGED
@@ -5,11 +5,16 @@ module Validate
|
|
5
5
|
#
|
6
6
|
class Validator
|
7
7
|
|
8
|
-
def initialize(
|
9
|
-
@validations = validations
|
8
|
+
def initialize(compiled_validations)
|
9
|
+
@validations = compiled_validations.validations
|
10
|
+
@allow_keys = compiled_validations.allow_keys
|
10
11
|
end
|
11
12
|
|
13
|
+
# TODO: this method could use some cleaning up...
|
14
|
+
#
|
12
15
|
def validates?(context)
|
16
|
+
context_hash = context.to_hash
|
17
|
+
|
13
18
|
@failures = @validations
|
14
19
|
.map do |v|
|
15
20
|
# destructure fields
|
@@ -32,14 +37,24 @@ module Validate
|
|
32
37
|
validator = if v[:validations]
|
33
38
|
Validator.new(v[:validations])
|
34
39
|
end
|
35
|
-
success = ValidationMethods.new.send(v[:name],
|
40
|
+
success = ValidationMethods.new.send(v[:name], context_hash, v[:fields], v[:opts], validator)
|
36
41
|
unless success
|
37
42
|
reason = v[:reason].is_a?(Proc) ?
|
38
|
-
ValidationMethods::ArgumentFailureBlockScope.new(
|
43
|
+
ValidationMethods::ArgumentFailureBlockScope.new(context_hash, v[:fields], v[:opts], validator).instance_exec(&v[:reason]) :
|
39
44
|
v[:reason]
|
40
45
|
{v[:fields] => reason}
|
41
46
|
end
|
42
47
|
end.select {|v| !v.nil? } # discard successes
|
48
|
+
|
49
|
+
if @allow_keys != :any
|
50
|
+
allow_keys = if @allow_keys == :valid
|
51
|
+
@validations.map {|v| v[:fields]}.flatten
|
52
|
+
else
|
53
|
+
@allow_keys
|
54
|
+
end
|
55
|
+
@failures.push(*(context_hash.keys - allow_keys).map {|k| {k => 'is not a valid key.'} })
|
56
|
+
end
|
57
|
+
|
43
58
|
@failures.count == 0
|
44
59
|
end
|
45
60
|
|
data/lib/validate/version.rb
CHANGED
data/spec/validate_spec.rb
CHANGED
@@ -248,11 +248,21 @@ describe Validate do
|
|
248
248
|
test = TestClass.new(field: {test: :val})
|
249
249
|
test.validates?.should == true
|
250
250
|
end
|
251
|
-
|
251
|
+
|
252
252
|
it 'fails' do
|
253
253
|
test = TestClass.new(field: {test: nil})
|
254
254
|
test.validates?.should == false
|
255
255
|
end
|
256
|
+
|
257
|
+
it 'passes arguments' do
|
258
|
+
class TestClass < BaseTestClass
|
259
|
+
validations do
|
260
|
+
validates :field, with: ->(o,k) { o[k] == :val }
|
261
|
+
end
|
262
|
+
end
|
263
|
+
test = TestClass.new(field: :val)
|
264
|
+
test.validates?.should == true
|
265
|
+
end
|
256
266
|
end
|
257
267
|
|
258
268
|
context 'validates_inclusion_of' do
|
@@ -544,6 +554,57 @@ describe Validate do
|
|
544
554
|
hash.failures.should == []
|
545
555
|
end
|
546
556
|
end
|
547
|
-
end
|
548
557
|
|
549
558
|
|
559
|
+
context 'when allow_keys' do
|
560
|
+
|
561
|
+
context 'is `:valid`' do
|
562
|
+
|
563
|
+
before do
|
564
|
+
class TestClass < BaseTestClass
|
565
|
+
validations do
|
566
|
+
allow_keys :valid
|
567
|
+
validates_type_of 'one', 'two', when: :is_set, is: Symbol
|
568
|
+
end
|
569
|
+
end
|
570
|
+
end
|
571
|
+
|
572
|
+
it 'should validate an object' do
|
573
|
+
test = TestClass.new({'one' => :hello})
|
574
|
+
test.validates?.should == true
|
575
|
+
end
|
576
|
+
|
577
|
+
it 'should not validate an invalid object' do
|
578
|
+
test = TestClass.new({'one' => :hello, 'three' => :hello})
|
579
|
+
test.validates?.should == false
|
580
|
+
test.failures.should == [{'three' => 'is not a valid key.'}]
|
581
|
+
end
|
582
|
+
|
583
|
+
end
|
584
|
+
|
585
|
+
context 'is an array' do
|
586
|
+
|
587
|
+
before do
|
588
|
+
class TestClass < BaseTestClass
|
589
|
+
validations do
|
590
|
+
allow_keys %w(one two)
|
591
|
+
end
|
592
|
+
end
|
593
|
+
end
|
594
|
+
|
595
|
+
it 'should validate an object' do
|
596
|
+
test = TestClass.new({'two' => :hello})
|
597
|
+
test.validates?.should == true
|
598
|
+
end
|
599
|
+
|
600
|
+
it 'should not validate an invalid object' do
|
601
|
+
test = TestClass.new({'one' => :hello, 'three' => :hello})
|
602
|
+
test.validates?.should == false
|
603
|
+
test.failures.should == [{'three' => 'is not a valid key.'}]
|
604
|
+
end
|
605
|
+
|
606
|
+
end
|
607
|
+
end
|
608
|
+
|
609
|
+
end
|
610
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: validate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: '1.3'
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-05-
|
12
|
+
date: 2013-05-30 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|