hash_validator 0.1.0 → 0.2.1

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.
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