hash_validator 0.1.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1db341e997808db63ae406e44a49d51b1ca45287
4
- data.tar.gz: b1d8af971d7c0fcdcdfb839bab7aec52092a4fc2
3
+ metadata.gz: fcfb909853b164442c3070897b294b05aad88a35
4
+ data.tar.gz: 6168c0b13dac5c47959bd9d8b98edaa82710857a
5
5
  SHA512:
6
- metadata.gz: 949b8a43860f1ec57f5fd3c23d0f18bb41dabf4615a215f636d6af7cbeb22cf69c78e20646bf6d4836ab38da28aaefe0e1fcd690e0df8867a3215a0b65b6e5a7
7
- data.tar.gz: 61e7ca533f2b11c352218104382a8d2b04a1db4ac62f11cd4eefe8daab9c95b4bcf2b8eca5f559a54d7d8d7445ca40b8f632fd6625e4938beb0e8d29360c4fea
6
+ metadata.gz: ee681f842e79645713cc7775eaf2e4d57cda92a90b52052e34d8a1b92717328a227b09f5c272d633753f3363e47f3cad899c24ffb9751836caf6cda75bdbb99c
7
+ data.tar.gz: e053babc5e9091973d04680c5a64e5aa11365701cfe1fc3e164a174341f3079bb48e6b9965009e2c58d988fdbb491c674a4f2b5ea28f6b09bf9ba15c0ccb669d
data/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # Hash Validator
2
2
 
3
- [![Build Status](https://travis-ci.org/JamesBrooks/hash_validator.png)](https://travis-ci.org/JamesBrooks/hash_validator)
4
- [![Code Climate](https://codeclimate.com/github/JamesBrooks/hash_validator.png)](https://codeclimate.com/github/JamesBrooks/hash_validator)
5
3
  [![Gem Version](https://badge.fury.io/rb/hash_validator.png)](http://badge.fury.io/rb/hash_validator)
4
+ [![Build Status](https://travis-ci.org/JamesBrooks/hash_validator.png)](https://travis-ci.org/JamesBrooks/hash_validator)
6
5
  [![Coverage Status](https://coveralls.io/repos/JamesBrooks/hash_validator/badge.png?branch=master)](https://coveralls.io/r/JamesBrooks/hash_validator)
6
+ [![Code Climate](https://codeclimate.com/github/JamesBrooks/hash_validator.png)](https://codeclimate.com/github/JamesBrooks/hash_validator)
7
7
  [![Dependency Status](https://gemnasium.com/JamesBrooks/hash_validator.png)](https://gemnasium.com/JamesBrooks/hash_validator)
8
8
 
9
9
  Ruby library to validate hashes (Hash) against user-defined requirements
@@ -53,7 +53,7 @@ validator.valid?
53
53
  validator.errors
54
54
  # {
55
55
  :user => {
56
- :last_name => "should be string",
56
+ :last_name => "string required",
57
57
  :age => "numeric required",
58
58
  :likes => "array required"
59
59
  }
@@ -71,8 +71,39 @@ Define a validation hash which will be used to validate. This has can be nested
71
71
  * `required`: just requires any value to be present for the designated key.
72
72
  * hashes are validates by nesting validations, or if just the presence of a hash is required `{}` can be used.
73
73
 
74
+ Additional validations exist to validate beyond simple typing, such as:
75
+
76
+ * `email`: email address validation (string + email address)
77
+
74
78
  Example use-cases include Ruby APIs (I'm currently using it in a Rails API that I'm building for better error responses to developers).
75
79
 
80
+ ## Custom validations
81
+
82
+ Allows custom defined validations (must inherit from `HashValidator::Validator::Base`). Example:
83
+
84
+ ```ruby
85
+ # Define our custom validator
86
+ class HashValidator::Validator::OddValidator < HashValidator::Validator::Base
87
+ def initialize
88
+ super('odd') # The name of the validator
89
+ end
90
+
91
+ def validate(key, value, validations, errors)
92
+ unless value.is_a?(Integer) && value.odd?
93
+ errors[key] = presence_error_message
94
+ end
95
+ end
96
+ end
97
+
98
+ # Add the validator
99
+ HashValidator.append_validator(HashValidator::Validator::OddValidator.new)
100
+
101
+ # Now the validator can be used! e.g.
102
+ validator = HashValidator.validate({ age: 27 }, { age: 'odd' })
103
+ validator.valid? # => true
104
+ validator.errors # => {}
105
+ ```
106
+
76
107
  ## Contributing
77
108
 
78
109
  1. Fork it
@@ -3,6 +3,14 @@ module HashValidator
3
3
 
4
4
 
5
5
  def self.append_validator(validator)
6
+ unless validator.is_a?(HashValidator::Validator::Base)
7
+ raise StandardError.new('validators need to inherit from HashValidator::Validator::Base')
8
+ end
9
+
10
+ if @@validators.detect { |v| v.name == validator.name }
11
+ raise StandardError.new('validators need to have unique names')
12
+ end
13
+
6
14
  @@validators << validator
7
15
  end
8
16
 
@@ -16,6 +24,8 @@ end
16
24
 
17
25
  # Load validators
18
26
  require 'hash_validator/validators/base'
27
+ require 'hash_validator/validators/simple_validator'
19
28
  require 'hash_validator/validators/hash_validator'
20
29
  require 'hash_validator/validators/presence_validator'
21
- require 'hash_validator/validators/simple_type_validator'
30
+ require 'hash_validator/validators/simple_type_validators'
31
+ require 'hash_validator/validators/email_validator'
@@ -1,6 +1,21 @@
1
1
  class HashValidator::Validator::Base
2
+ attr_accessor :name
3
+
4
+
5
+ def initialize(name)
6
+ unless name.is_a?(String) && name.size > 0
7
+ raise StandardError.new('Validator must be initialized with a valid name (string with length greater than zero)')
8
+ end
9
+
10
+ self.name = name
11
+ end
12
+
2
13
  def should_validate?(name)
3
- raise StandardError.new('should_validate? should not be called directly on BaseValidator')
14
+ self.name == name
15
+ end
16
+
17
+ def presence_error_message
18
+ "#{self.name} required"
4
19
  end
5
20
 
6
21
  def validate(key, value, validations, errors)
@@ -0,0 +1,17 @@
1
+ class HashValidator::Validator::EmailValidator < HashValidator::Validator::Base
2
+ def initialize
3
+ super('email') # The name of the validator
4
+ end
5
+
6
+ def presence_error_message
7
+ 'is not a valid email'
8
+ end
9
+
10
+ def validate(key, value, validations, errors)
11
+ unless value.is_a?(String) && value.include?("@")
12
+ errors[key] = presence_error_message
13
+ end
14
+ end
15
+ end
16
+
17
+ HashValidator.append_validator(HashValidator::Validator::EmailValidator.new)
@@ -1,10 +1,6 @@
1
1
  class HashValidator::Validator::HashValidator < HashValidator::Validator::Base
2
- def name
3
- 'hash'
4
- end
5
-
6
- def presence_error_message
7
- "#{name} required"
2
+ def initialize
3
+ super('hash')
8
4
  end
9
5
 
10
6
  def should_validate?(rhs)
@@ -1,16 +1,12 @@
1
1
  class HashValidator::Validator::PresenceValidator < HashValidator::Validator::Base
2
- def name
3
- 'required'
2
+ def initialize
3
+ super('required')
4
4
  end
5
5
 
6
6
  def presence_error_message
7
7
  'is required'
8
8
  end
9
9
 
10
- def should_validate?(rhs)
11
- rhs == name
12
- end
13
-
14
10
  def validate(key, value, validations, errors)
15
11
  unless value
16
12
  errors[key] = presence_error_message
@@ -18,5 +14,4 @@ class HashValidator::Validator::PresenceValidator < HashValidator::Validator::Ba
18
14
  end
19
15
  end
20
16
 
21
-
22
17
  HashValidator.append_validator(HashValidator::Validator::PresenceValidator.new)
@@ -0,0 +1,8 @@
1
+ [
2
+ [ 'array', Array ],
3
+ [ 'numeric', Numeric ],
4
+ [ 'string', String ],
5
+ [ 'time', Time ]
6
+ ].each do |name, klass|
7
+ HashValidator.append_validator(HashValidator::Validator::SimpleValidator.new(name, lambda { |v| v.is_a?(klass) }))
8
+ end
@@ -0,0 +1,20 @@
1
+ class HashValidator::Validator::SimpleValidator < HashValidator::Validator::Base
2
+ attr_accessor :lambda
3
+
4
+
5
+ def initialize(name, lambda)
6
+ # lambda must accept one argument (the value)
7
+ if lambda.arity != 1
8
+ raise StandardError.new("lambda should take only one argument - passed lambda takes #{lambda.arity}")
9
+ end
10
+
11
+ super(name)
12
+ self.lambda = lambda
13
+ end
14
+
15
+ def validate(key, value, validations, errors)
16
+ unless lambda.call(value)
17
+ errors[key] = presence_error_message
18
+ end
19
+ end
20
+ end
@@ -1,3 +1,3 @@
1
1
  module HashValidator
2
- VERSION = '0.1.0'
2
+ VERSION = '0.2.1'
3
3
  end
@@ -1,166 +1,192 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe HashValidator do
4
- describe 'individual type validations' do
5
- it 'should validate hash' do
6
- validate({ v: {} }, { v: {} }).valid?.should be_true
7
-
8
- validate({ v: '' }, { v: {} }).valid?.should be_false
9
- validate({ v: '' }, { v: {} }).errors.should eq({ v: 'hash required' })
4
+ describe 'Adding validators' do
5
+ let(:new_validator1) { HashValidator::Validator::SimpleValidator.new('my_type1', lambda { |v| true }) }
6
+ let(:new_validator2) { HashValidator::Validator::SimpleValidator.new('my_type2', lambda { |v| true }) }
7
+
8
+ it 'allows validators with unique names' do
9
+ expect {
10
+ HashValidator.append_validator(new_validator1)
11
+ }.to_not raise_error
10
12
  end
11
13
 
12
- it 'should validate presence' do
13
- validate({ v: 'test' }, { v: 'required' }).valid?.should be_true
14
- validate({ v: 1234 }, { v: 'required' }).valid?.should be_true
15
-
16
- validate({ v: nil }, { v: 'required' }).valid?.should be_false
17
- validate({ v: nil }, { v: 'required' }).errors.should eq({ v: 'is required' })
18
-
19
- validate({ x: 'test' }, { v: 'required' }).valid?.should be_false
20
- validate({ x: 'test' }, { v: 'required' }).errors.should eq({ v: 'is required' })
21
-
22
- validate({ x: 1234 }, { v: 'required' }).valid?.should be_false
23
- validate({ x: 1234 }, { v: 'required' }).errors.should eq({ v: 'is required' })
14
+ it 'does not allow validators with conflicting names' do
15
+ expect {
16
+ HashValidator.append_validator(new_validator2)
17
+ HashValidator.append_validator(new_validator2)
18
+ }.to raise_error(StandardError, 'validators need to have unique names')
24
19
  end
25
20
 
26
- it 'should validate string' do
27
- validate({ v: 'test' }, { v: 'string' }).valid?.should be_true
28
-
29
- validate({ v: 123456 }, { v: 'string' }).valid?.should be_false
30
- validate({ v: 123456 }, { v: 'string' }).errors.should eq({ v: 'string required' })
21
+ it 'does not allow validators that do not inherit from the base validator class' do
22
+ expect {
23
+ HashValidator.append_validator('Not a validator')
24
+ }.to raise_error(StandardError, 'validators need to inherit from HashValidator::Validator::Base')
31
25
  end
26
+ end
32
27
 
33
- it 'should validate numeric' do
34
- validate({ v: 1234 }, { v: 'numeric' }).valid?.should be_true
35
- validate({ v: '12' }, { v: 'numeric' }).valid?.should be_false
36
- end
28
+ describe '#validate' do
29
+ describe 'individual type validations' do
30
+ it 'should validate hash' do
31
+ validate({ v: {} }, { v: {} }).valid?.should be_true
37
32
 
38
- it 'should validate array' do
39
- validate({ v: [ 1,2,3 ] }, { v: 'array' }).valid?.should be_true
40
- validate({ v: ' 1,2,3 ' }, { v: 'array' }).valid?.should be_false
41
- end
33
+ validate({ v: '' }, { v: {} }).valid?.should be_false
34
+ validate({ v: '' }, { v: {} }).errors.should eq({ v: 'hash required' })
35
+ end
42
36
 
43
- it 'should validate time' do
44
- validate({ v: Time.now }, { v: 'time' }).valid?.should be_true
45
- validate({ v: '2013-04-12 13:18:05 +0930' }, { v: 'time' }).valid?.should be_false
46
- end
47
- end
37
+ it 'should validate presence' do
38
+ validate({ v: 'test' }, { v: 'required' }).valid?.should be_true
39
+ validate({ v: 1234 }, { v: 'required' }).valid?.should be_true
48
40
 
49
- describe 'full validations' do
50
- let(:empty_hash) {{}}
51
-
52
- let(:simple_hash) {{
53
- foo: 1,
54
- bar: 'baz'
55
- }}
56
-
57
- let(:invalid_simple_hash) {{
58
- foo: 1,
59
- bar: 2
60
- }}
61
-
62
- let(:complex_hash) {{
63
- foo: 1,
64
- bar: 'baz',
65
- user: {
66
- first_name: 'James',
67
- last_name: 'Brooks',
68
- age: 27,
69
- likes: [ 'Ruby', 'Kendo', 'Board Games' ]
70
- }
71
- }}
72
-
73
- let(:invalid_complex_hash) {{
74
- foo: 1,
75
- bar: 2,
76
- user: {
77
- first_name: 'James',
78
- last_name: 'Brooks',
79
- likes: 'Ruby, Kendo, Board Games'
80
- }
81
- }}
82
-
83
- describe 'no validations' do
84
- let(:validations) {{}}
85
-
86
- it 'should validate an empty hash' do
87
- v = validate(empty_hash, validations)
88
- v.valid?.should be_true
89
- v.errors.should be_empty
90
- end
41
+ validate({ v: nil }, { v: 'required' }).valid?.should be_false
42
+ validate({ v: nil }, { v: 'required' }).errors.should eq({ v: 'is required' })
91
43
 
92
- it 'should validate a simple hash' do
93
- v = validate(simple_hash, validations)
94
- v.valid?.should be_true
95
- v.errors.should be_empty
96
- end
44
+ validate({ x: 'test' }, { v: 'required' }).valid?.should be_false
45
+ validate({ x: 'test' }, { v: 'required' }).errors.should eq({ v: 'is required' })
97
46
 
98
- it 'should validate a simple hash 2' do
99
- v = validate(invalid_simple_hash, validations)
100
- v.valid?.should be_true
101
- v.errors.should be_empty
47
+ validate({ x: 1234 }, { v: 'required' }).valid?.should be_false
48
+ validate({ x: 1234 }, { v: 'required' }).errors.should eq({ v: 'is required' })
102
49
  end
103
50
 
104
- it 'should validate a complex hash' do
105
- v = validate(complex_hash, validations)
106
- v.valid?.should be_true
107
- v.errors.should be_empty
108
- end
51
+ it 'should validate string' do
52
+ validate({ v: 'test' }, { v: 'string' }).valid?.should be_true
109
53
 
110
- it 'should validate a complex hash 2' do
111
- v = validate(invalid_complex_hash, validations)
112
- v.valid?.should be_true
113
- v.errors.should be_empty
54
+ validate({ v: 123456 }, { v: 'string' }).valid?.should be_false
55
+ validate({ v: 123456 }, { v: 'string' }).errors.should eq({ v: 'string required' })
114
56
  end
115
- end
116
57
 
117
- describe 'simple validations' do
118
- let(:validations) {{ foo: 'numeric', bar: 'string' }}
119
-
120
- it 'should not validate an empty hash (stating missing with required)' do
121
- v = validate(empty_hash, validations)
122
- v.valid?.should be_false
123
- v.errors.should eq({ foo: 'numeric required', bar: 'string required' })
58
+ it 'should validate numeric' do
59
+ validate({ v: 1234 }, { v: 'numeric' }).valid?.should be_true
60
+ validate({ v: '12' }, { v: 'numeric' }).valid?.should be_false
124
61
  end
125
62
 
126
- it 'should validate a simple hash' do
127
- v = validate(simple_hash, validations)
128
- v.valid?.should be_true
129
- v.errors.should be_empty
63
+ it 'should validate array' do
64
+ validate({ v: [ 1,2,3 ] }, { v: 'array' }).valid?.should be_true
65
+ validate({ v: ' 1,2,3 ' }, { v: 'array' }).valid?.should be_false
130
66
  end
131
67
 
132
- it 'should not validate a simple hash 2' do
133
- v = validate(invalid_simple_hash, validations)
134
- v.valid?.should be_false
135
- v.errors.should eq({ bar: 'string required' })
68
+ it 'should validate time' do
69
+ validate({ v: Time.now }, { v: 'time' }).valid?.should be_true
70
+ validate({ v: '2013-04-12 13:18:05 +0930' }, { v: 'time' }).valid?.should be_false
136
71
  end
72
+ end
137
73
 
138
- it 'should validate a complex hash' do
139
- v = validate(complex_hash, validations)
140
- v.valid?.should be_true
141
- v.errors.should be_empty
74
+ describe 'full validations' do
75
+ let(:empty_hash) {{}}
76
+
77
+ let(:simple_hash) {{
78
+ foo: 1,
79
+ bar: 'baz'
80
+ }}
81
+
82
+ let(:invalid_simple_hash) {{
83
+ foo: 1,
84
+ bar: 2
85
+ }}
86
+
87
+ let(:complex_hash) {{
88
+ foo: 1,
89
+ bar: 'baz',
90
+ user: {
91
+ first_name: 'James',
92
+ last_name: 'Brooks',
93
+ age: 27,
94
+ likes: [ 'Ruby', 'Kendo', 'Board Games' ]
95
+ }
96
+ }}
97
+
98
+ let(:invalid_complex_hash) {{
99
+ foo: 1,
100
+ bar: 2,
101
+ user: {
102
+ first_name: 'James',
103
+ last_name: 'Brooks',
104
+ likes: 'Ruby, Kendo, Board Games'
105
+ }
106
+ }}
107
+
108
+ describe 'no validations' do
109
+ let(:validations) {{}}
110
+
111
+ it 'should validate an empty hash' do
112
+ v = validate(empty_hash, validations)
113
+ v.valid?.should be_true
114
+ v.errors.should be_empty
115
+ end
116
+
117
+ it 'should validate a simple hash' do
118
+ v = validate(simple_hash, validations)
119
+ v.valid?.should be_true
120
+ v.errors.should be_empty
121
+ end
122
+
123
+ it 'should validate a simple hash 2' do
124
+ v = validate(invalid_simple_hash, validations)
125
+ v.valid?.should be_true
126
+ v.errors.should be_empty
127
+ end
128
+
129
+ it 'should validate a complex hash' do
130
+ v = validate(complex_hash, validations)
131
+ v.valid?.should be_true
132
+ v.errors.should be_empty
133
+ end
134
+
135
+ it 'should validate a complex hash 2' do
136
+ v = validate(invalid_complex_hash, validations)
137
+ v.valid?.should be_true
138
+ v.errors.should be_empty
139
+ end
142
140
  end
143
141
 
144
- it 'should not validate a complex hash 2' do
145
- v = validate(invalid_complex_hash, validations)
146
- v.valid?.should be_false
147
- v.errors.should eq({ bar: 'string required' })
142
+ describe 'simple validations' do
143
+ let(:validations) {{ foo: 'numeric', bar: 'string' }}
144
+
145
+ it 'should not validate an empty hash (stating missing with required)' do
146
+ v = validate(empty_hash, validations)
147
+ v.valid?.should be_false
148
+ v.errors.should eq({ foo: 'numeric required', bar: 'string required' })
149
+ end
150
+
151
+ it 'should validate a simple hash' do
152
+ v = validate(simple_hash, validations)
153
+ v.valid?.should be_true
154
+ v.errors.should be_empty
155
+ end
156
+
157
+ it 'should not validate a simple hash 2' do
158
+ v = validate(invalid_simple_hash, validations)
159
+ v.valid?.should be_false
160
+ v.errors.should eq({ bar: 'string required' })
161
+ end
162
+
163
+ it 'should validate a complex hash' do
164
+ v = validate(complex_hash, validations)
165
+ v.valid?.should be_true
166
+ v.errors.should be_empty
167
+ end
168
+
169
+ it 'should not validate a complex hash 2' do
170
+ v = validate(invalid_complex_hash, validations)
171
+ v.valid?.should be_false
172
+ v.errors.should eq({ bar: 'string required' })
173
+ end
148
174
  end
149
- end
150
175
 
151
- describe 'nested validations' do
152
- let(:validations) {{ foo: 'numeric', bar: 'string', user: { first_name: 'string', age: 'required', likes: 'array' } }}
176
+ describe 'nested validations' do
177
+ let(:validations) {{ foo: 'numeric', bar: 'string', user: { first_name: 'string', age: 'required', likes: 'array' } }}
153
178
 
154
- it 'should validate a complex hash' do
155
- v = validate(complex_hash, validations)
156
- v.valid?.should be_true
157
- v.errors.should be_empty
158
- end
179
+ it 'should validate a complex hash' do
180
+ v = validate(complex_hash, validations)
181
+ v.valid?.should be_true
182
+ v.errors.should be_empty
183
+ end
159
184
 
160
- it 'should not validate a complex hash 2' do
161
- v = validate(invalid_complex_hash, validations)
162
- v.valid?.should be_false
163
- v.errors.should eq({ bar: 'string required', user: { age: 'is required', likes: 'array required' } })
185
+ it 'should not validate a complex hash 2' do
186
+ v = validate(invalid_complex_hash, validations)
187
+ v.valid?.should be_false
188
+ v.errors.should eq({ bar: 'string required', user: { age: 'is required', likes: 'array required' } })
189
+ end
164
190
  end
165
191
  end
166
192
  end
@@ -1,16 +1,23 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe HashValidator::Validator::Base do
4
- let(:validator) { HashValidator::Validator::Base.new }
4
+ let(:name) { 'my_validator' }
5
5
 
6
- describe '#should_validate?' do
7
- it 'throws an exception' do
8
- expect { validator.should_validate?('name') }.to raise_error(StandardError, 'should_validate? should not be called directly on BaseValidator')
9
- end
6
+
7
+ it 'allows a validator to be created with a valid name' do
8
+ expect { HashValidator::Validator::Base.new(name) }.to_not raise_error
9
+ end
10
+
11
+ it 'does not allow a validator to be created with an invalid name' do
12
+ expect { HashValidator::Validator::Base.new(nil) }.to raise_error(StandardError, 'Validator must be initialized with a valid name (string with length greater than zero)')
13
+ expect { HashValidator::Validator::Base.new(123) }.to raise_error(StandardError, 'Validator must be initialized with a valid name (string with length greater than zero)')
14
+ expect { HashValidator::Validator::Base.new('') }.to raise_error(StandardError, 'Validator must be initialized with a valid name (string with length greater than zero)')
10
15
  end
11
16
 
12
17
  describe '#validate' do
13
- it 'throws an exception' do
18
+ let(:validator) { HashValidator::Validator::Base.new('test') }
19
+
20
+ it 'throws an exception as base validators cant actually validate' do
14
21
  expect { validator.validate('key', 'value', {}, {}) }.to raise_error(StandardError, 'validate should not be called directly on BaseValidator')
15
22
  end
16
23
  end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ describe HashValidator::Validator::Base do
4
+ let(:validator) { HashValidator::Validator::EmailValidator.new }
5
+ let(:errors) { Hash.new }
6
+
7
+ describe '#should_validate?' do
8
+ it 'should validate the name "email"' do
9
+ validator.should_validate?('email').should be_true
10
+ end
11
+
12
+ it 'should not validate other names' do
13
+ validator.should_validate?('string').should be_false
14
+ validator.should_validate?('array').should be_false
15
+ validator.should_validate?(nil).should be_false
16
+ end
17
+ end
18
+
19
+ describe '#validate' do
20
+ it 'should validate an email with true' do
21
+ validator.validate(:key, "johndoe@gmail.com", {}, errors)
22
+
23
+ errors.should be_empty
24
+ end
25
+
26
+ it 'should validate a string without an @ symbol with false' do
27
+ validator.validate(:key, 'test', {}, errors)
28
+
29
+ errors.should_not be_empty
30
+ errors.should eq({ key: 'is not a valid email' })
31
+ end
32
+
33
+ it 'should validate a number with false' do
34
+ validator.validate(:key, 123, {}, errors)
35
+
36
+ errors.should_not be_empty
37
+ errors.should eq({ key: 'is not a valid email' })
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+
3
+ describe HashValidator::Validator::SimpleValidator do
4
+ describe '#initialize' do
5
+ it 'accepts blocks with one argument' do
6
+ expect {
7
+ HashValidator::Validator::SimpleValidator.new('name', lambda { |a| true })
8
+ }.to_not raise_error
9
+ end
10
+
11
+ it 'does not accept blocks with no arguments' do
12
+ expect {
13
+ HashValidator::Validator::SimpleValidator.new('name', lambda { true })
14
+ }.to raise_error(StandardError, 'lambda should take only one argument - passed lambda takes 0')
15
+ end
16
+
17
+ it 'does not accept blocks with two arguments' do
18
+ expect {
19
+ HashValidator::Validator::SimpleValidator.new('name', lambda { |a,b| true })
20
+ }.to raise_error(StandardError, 'lambda should take only one argument - passed lambda takes 2')
21
+ end
22
+ end
23
+
24
+ describe '#validate' do
25
+ # Lambda that accepts strings that are 4 characters or shorter
26
+ let(:short_string_lambda) { lambda { |v| v.is_a?(String) && v.size < 5 } }
27
+ let(:short_string_validator) { HashValidator::Validator::SimpleValidator.new('short_string', short_string_lambda) }
28
+ let(:errors) { Hash.new }
29
+
30
+ [ '', '1', '12', '123', '1234' ].each do |value|
31
+ it "validates the string '#{value}'" do
32
+ short_string_validator.validate(:key, value, {}, errors)
33
+
34
+ errors.should be_empty
35
+ end
36
+ end
37
+
38
+ [ nil, '12345', '123456', 123, 123456, Time.now, (1..5) ].each do |value|
39
+ it "does not validate bad value '#{value}'" do
40
+ short_string_validator.validate(:key, value, {}, errors)
41
+
42
+ errors.should eq({ key: 'short_string required' })
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Simple validator types' do
4
+ let(:errors) { Hash.new }
5
+
6
+ # Simple types
7
+ {
8
+ string: {
9
+ valid: [ '', 'Hello World', '12345' ],
10
+ invalid: [ nil, 12345, Time.now ]
11
+ },
12
+ numeric: {
13
+ valid: [ 0, 123, 123.45 ],
14
+ invalid: [ nil, '', '123', Time.now ]
15
+ },
16
+ array: {
17
+ valid: [ [], [1], ['foo'], [1,['foo'],Time.now] ],
18
+ invalid: [ nil, '', 123, '123', Time.now, '[1]' ]
19
+ },
20
+ time: {
21
+ valid: [ Time.now ],
22
+ invalid: [ nil, '', 123, '123', "#{Time.now}" ]
23
+ }
24
+ }.each do |type, data|
25
+ describe type do
26
+ data[:valid].each do |value|
27
+ it "validates '#{value}' successful" do
28
+ validator = HashValidator.validate({ v: value }, { v: type.to_s })
29
+
30
+ validator.valid?.should be_true
31
+ validator.errors.should be_empty
32
+ end
33
+ end
34
+
35
+ data[:invalid].each do |value|
36
+ it "validates '#{value}' with failure" do
37
+ validator = HashValidator.validate({ v: value }, { v: type.to_s })
38
+
39
+ validator.valid?.should be_false
40
+ validator.errors.should eq({ v: "#{type} required" })
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,95 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'User-defined validator' do
4
+ let(:validator) do
5
+ unless defined?(HashValidator::Validator::OddValidator)
6
+ # Define our custom validator
7
+ class HashValidator::Validator::OddValidator < HashValidator::Validator::Base
8
+ def initialize
9
+ super('odd')
10
+ end
11
+
12
+ def validate(key, value, validations, errors)
13
+ unless value.is_a?(Integer) && value.odd?
14
+ errors[key] = presence_error_message
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ HashValidator::Validator::OddValidator.new
21
+ end
22
+
23
+ let(:errors) { Hash.new }
24
+
25
+
26
+ describe '#should_validate?' do
27
+ it 'validates the name "odd"' do
28
+ validator.should_validate?('odd').should be_true
29
+ end
30
+
31
+ it 'does not validate other names' do
32
+ validator.should_validate?('string').should be_false
33
+ validator.should_validate?('array').should be_false
34
+ validator.should_validate?(nil).should be_false
35
+ end
36
+ end
37
+
38
+ describe '#validate' do
39
+ it 'validates odd integers with true' do
40
+ validator.validate(:key, 1, {}, errors)
41
+
42
+ errors.should be_empty
43
+ end
44
+
45
+ it 'validates even integers with errrors' do
46
+ validator.validate(:key, 2, {}, errors)
47
+
48
+ errors.should_not be_empty
49
+ errors.should eq({ key: 'odd required' })
50
+ end
51
+
52
+ it 'validates even floats with errrors' do
53
+ validator.validate(:key, 2.0, {}, errors)
54
+
55
+ errors.should_not be_empty
56
+ errors.should eq({ key: 'odd required' })
57
+ end
58
+
59
+ it 'validates odd floats with errrors' do
60
+ validator.validate(:key, 1.0, {}, errors)
61
+
62
+ errors.should_not be_empty
63
+ errors.should eq({ key: 'odd required' })
64
+ end
65
+
66
+ it 'validates an odd integer string with errrors' do
67
+ validator.validate(:key, '1', {}, errors)
68
+
69
+ errors.should_not be_empty
70
+ errors.should eq({ key: 'odd required' })
71
+ end
72
+ end
73
+
74
+ describe 'Integrating with the entire validation system' do
75
+ before { HashValidator.append_validator(validator) rescue nil } # rescue to prevent: validators need to have unique names
76
+
77
+ it 'can be looked up using #validator_for' do
78
+ HashValidator.validator_for('odd').should be_a_kind_of(HashValidator::Validator::OddValidator)
79
+ end
80
+
81
+ it 'can be used in validations - test 1' do
82
+ validator = HashValidator.validate({ age: 27 }, { age: 'odd' })
83
+
84
+ validator.valid?.should be_true
85
+ validator.errors.should be_empty
86
+ end
87
+
88
+ it 'can be used in validations - test 2' do
89
+ validator = HashValidator.validate({ age: 40 }, { age: 'odd' })
90
+
91
+ validator.valid?.should be_false
92
+ validator.errors.should eq({ age: 'odd required' })
93
+ end
94
+ end
95
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hash_validator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Brooks
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-04-17 00:00:00.000000000 Z
11
+ date: 2013-07-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -85,16 +85,21 @@ files:
85
85
  - lib/hash_validator/base.rb
86
86
  - lib/hash_validator/validators.rb
87
87
  - lib/hash_validator/validators/base.rb
88
+ - lib/hash_validator/validators/email_validator.rb
88
89
  - lib/hash_validator/validators/hash_validator.rb
89
90
  - lib/hash_validator/validators/presence_validator.rb
90
- - lib/hash_validator/validators/simple_type_validator.rb
91
+ - lib/hash_validator/validators/simple_type_validators.rb
92
+ - lib/hash_validator/validators/simple_validator.rb
91
93
  - lib/hash_validator/version.rb
92
94
  - spec/hash_validator_spec.rb
93
95
  - spec/hash_validator_spec_helper.rb
94
96
  - spec/spec_helper.rb
95
97
  - spec/validators/base_spec.rb
98
+ - spec/validators/email_spec.rb
96
99
  - spec/validators/presence_spec.rb
97
- - spec/validators/simple_type_spec.rb
100
+ - spec/validators/simple_spec.rb
101
+ - spec/validators/simple_types_spec.rb
102
+ - spec/validators/user_defined_spec.rb
98
103
  homepage: https://github.com/JamesBrooks/hash_validator
99
104
  licenses:
100
105
  - MIT
@@ -124,5 +129,8 @@ test_files:
124
129
  - spec/hash_validator_spec_helper.rb
125
130
  - spec/spec_helper.rb
126
131
  - spec/validators/base_spec.rb
132
+ - spec/validators/email_spec.rb
127
133
  - spec/validators/presence_spec.rb
128
- - spec/validators/simple_type_spec.rb
134
+ - spec/validators/simple_spec.rb
135
+ - spec/validators/simple_types_spec.rb
136
+ - spec/validators/user_defined_spec.rb
@@ -1,32 +0,0 @@
1
- class HashValidator::Validator::SimpleTypeValidator < HashValidator::Validator::Base
2
- attr_accessor :name, :klass
3
-
4
-
5
- def initialize(name, klass)
6
- self.name = name
7
- self.klass = klass
8
- end
9
-
10
- def presence_error_message
11
- "#{name} required"
12
- end
13
-
14
- def should_validate?(rhs)
15
- rhs == self.name
16
- end
17
-
18
- def validate(key, value, validations, errors)
19
- unless value.is_a?(klass)
20
- errors[key] = presence_error_message
21
- end
22
- end
23
- end
24
-
25
-
26
- # Create simple type validators
27
- [
28
- [ 'array', Array ],
29
- [ 'numeric', Numeric ],
30
- [ 'string', String ],
31
- [ 'time', Time ]
32
- ].each { |name, klass| HashValidator.append_validator(HashValidator::Validator::SimpleTypeValidator.new(name, klass)) }
@@ -1,34 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe HashValidator::Validator::Base do
4
- let(:my_class) { Class.new }
5
- let(:validator) { HashValidator::Validator::SimpleTypeValidator.new('my_class', my_class) }
6
- let(:errors) { Hash.new }
7
-
8
- describe '#should_validate?' do
9
- it 'should validate the name "my_class"' do
10
- validator.should_validate?('my_class').should be_true
11
- end
12
-
13
- it 'should not validate other names' do
14
- validator.should_validate?('string').should be_false
15
- validator.should_validate?('array').should be_false
16
- validator.should_validate?(nil).should be_false
17
- end
18
- end
19
-
20
- describe '#validate' do
21
- it 'should validate the my_class class with true' do
22
- validator.validate(:key, my_class.new, {}, errors)
23
-
24
- errors.should be_empty
25
- end
26
-
27
- it 'should validate other classes with errrors' do
28
- validator.validate(:key, "foo bar", {}, errors)
29
-
30
- errors.should_not be_empty
31
- errors.should eq({ key: 'my_class required' })
32
- end
33
- end
34
- end