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.
@@ -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
- attr_reader :validations
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
- # when -> { ... } do
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
 
@@ -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
- true == obj[field].instance_exec(&opts[:with])
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 of in #{opts[:is].inspect}." }
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
@@ -5,11 +5,16 @@ module Validate
5
5
  #
6
6
  class Validator
7
7
 
8
- def initialize(validations)
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], context.to_hash, v[:fields], v[:opts], validator)
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(context.to_hash, v[:fields], v[:opts], validator).instance_exec(&v[:reason]) :
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
 
@@ -1,4 +1,4 @@
1
1
 
2
2
  module Validate
3
- VERSION = '1.2.1'
3
+ VERSION = '1.3'
4
4
  end
@@ -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.2.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-02 00:00:00.000000000 Z
12
+ date: 2013-05-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec