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