hash_validator 0.0.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2e41604544ea1db1c1d88b8c49c59d7edcc96821
4
+ data.tar.gz: 5b5f86c50484ffdf9784534ce3e33ccf150fb0bb
5
+ SHA512:
6
+ metadata.gz: 11f7746ceca1018580e21d7f05a6ceae369339c94cd1f28ad40303e8f68534b5b9355293f96c483dd59ef9bbb2c09aa2a6c97cc764828d73e0ec7150293662ad
7
+ data.tar.gz: 3d97b917af1eba349ca698cd823dd9e4c53bec687ea82c12315682d2d283ca10bdb53c2230915c645d552d95d65e3d7881ee74ea222b2bfa2392036073cd892c
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.2
4
+ - 1.9.3
5
+ - 2.0.0
6
+ - jruby-19mode
7
+ - rbx-19mode
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in hash_validator.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 James Brooks
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,77 @@
1
+ # Hash Validator
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/git-runner)
5
+ [![Gem Version](https://badge.fury.io/rb/hash_validator.png)](http://badge.fury.io/rb/git-runner)
6
+ [![Dependency Status](https://gemnasium.com/JamesBrooks/hash_validator.png)](https://gemnasium.com/JamesBrooks/git-runner)
7
+
8
+ Ruby library to validate hashes (Hash) against user-defined requirements
9
+
10
+ ## Installation
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ gem 'hash_validator'
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install hash_validator
23
+
24
+ ## Example
25
+ ````
26
+ # Validations hash
27
+ validations = {
28
+ user: {
29
+ first_name: 'string',
30
+ last_name: 'string',
31
+ age: 'numeric',
32
+ likes: 'array'
33
+ }
34
+ }
35
+
36
+ # Hash to validate
37
+ hash = {
38
+ foo: 1,
39
+ bar: 'baz',
40
+ user: {
41
+ first_name: 'James',
42
+ last_name: 12345
43
+ }
44
+ }
45
+
46
+ validator = HashValidator.validate(hash, validations)
47
+
48
+ validator.valid?
49
+ # => false
50
+
51
+ validator.errors
52
+ # {
53
+ :user => {
54
+ :last_name => "should be string",
55
+ :age => "numeric required",
56
+ :likes => "array required"
57
+ }
58
+ }
59
+ ````
60
+
61
+ ## Usage
62
+
63
+ Define a validation hash which will be used to validate. This has can be nested as deeply as required using the following values to validate specific value types:
64
+
65
+ * `string`
66
+ * `numeric`
67
+ * `array`
68
+ * `time`
69
+ * hashes are validates by nesting validations, or if just the presence of a hash is required `{}` can be used.
70
+
71
+ ## Contributing
72
+
73
+ 1. Fork it
74
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
75
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
76
+ 4. Push to the branch (`git push origin my-new-feature`)
77
+ 5. Create new Pull Request
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new('spec')
5
+
6
+ task :default => :spec
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'hash_validator/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "hash_validator"
8
+ spec.version = HashValidator::VERSION
9
+ spec.authors = ["James Brooks"]
10
+ spec.email = ["james@gooddogdesign.com"]
11
+ spec.description = "Ruby library to validate hashes (Hash) against user-defined requirements"
12
+ spec.summary = "Ruby library to validate hashes (Hash) against user-defined requirements"
13
+ spec.homepage = "https://github.com/JamesBrooks/hash_validator"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency 'bundler', '~> 1.3'
22
+ spec.add_development_dependency 'rake'
23
+ spec.add_development_dependency 'rspec', '~> 2.13.0'
24
+ end
@@ -0,0 +1,9 @@
1
+ require 'hash_validator/base'
2
+ require 'hash_validator/version'
3
+ require 'hash_validator/validators'
4
+
5
+ module HashValidator
6
+ def self.validate(*args)
7
+ Base.validate(*args)
8
+ end
9
+ end
@@ -0,0 +1,27 @@
1
+ class HashValidator::Base
2
+ attr_accessor :hash, :validations, :errors
3
+
4
+
5
+ def initialize(hash, validations)
6
+ self.errors = {}
7
+ self.hash = hash
8
+ self.validations = validations
9
+
10
+ validate
11
+ end
12
+
13
+ def valid?
14
+ errors.empty?
15
+ end
16
+
17
+ def self.validate(hash, validations)
18
+ new(hash, validations)
19
+ end
20
+
21
+
22
+ private
23
+ def validate
24
+ HashValidator.validator_for(hash).validate(:base, self.hash, self.validations, self.errors)
25
+ self.errors = errors[:base]
26
+ end
27
+ end
@@ -0,0 +1,20 @@
1
+ module HashValidator
2
+ @@validators = []
3
+
4
+
5
+ def self.append_validator(validator)
6
+ @@validators << validator
7
+ end
8
+
9
+ def self.validator_for(rhs)
10
+ @@validators.detect { |v| v.should_validate?(rhs) } || raise(StandardError.new("Could not find valid validator for: #{rhs}"))
11
+ end
12
+
13
+ module Validator
14
+ end
15
+ end
16
+
17
+ # Load validators
18
+ require 'hash_validator/validators/base'
19
+ require 'hash_validator/validators/hash_validator'
20
+ require 'hash_validator/validators/simple_type_validator'
@@ -0,0 +1,9 @@
1
+ class HashValidator::Validator::Base
2
+ def should_validate?(name)
3
+ raise StandardError.new('should_validate? should not be called directly on BaseValidator')
4
+ end
5
+
6
+ def validate(key, value, validations, errors)
7
+ raise StandardError.new('validate should not be called directly on BaseValidator')
8
+ end
9
+ end
@@ -0,0 +1,38 @@
1
+ class HashValidator::Validator::HashValidator < HashValidator::Validator::Base
2
+ def name
3
+ 'hash'
4
+ end
5
+
6
+ def should_validate?(rhs)
7
+ rhs.is_a?(Hash)
8
+ end
9
+
10
+ def validate(key, value, validations, errors)
11
+ # Validate hash
12
+ unless value.is_a?(Hash)
13
+ errors[name] = 'should be hash'
14
+ return
15
+ end
16
+
17
+ # Hashes can contain sub-elements, attempt to validator those
18
+ errors = (errors[key] = {})
19
+
20
+ validations.each do |v_key, v_value|
21
+ validator = HashValidator.validator_for(v_value)
22
+
23
+ # Key presence
24
+ unless value[v_key]
25
+ errors[v_key] = "#{validator.name} required"
26
+ next
27
+ end
28
+
29
+ validator.validate(v_key, value[v_key], v_value, errors)
30
+ end
31
+
32
+ # Cleanup errors (remove any empty nested errors)
33
+ errors.delete_if { |k,v| v.empty? }
34
+ end
35
+ end
36
+
37
+
38
+ HashValidator.append_validator(HashValidator::Validator::HashValidator.new)
@@ -0,0 +1,28 @@
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 should_validate?(rhs)
11
+ rhs == self.name
12
+ end
13
+
14
+ def validate(key, value, validations, errors)
15
+ unless value.is_a?(klass)
16
+ errors[key] = "should be #{name}"
17
+ end
18
+ end
19
+ end
20
+
21
+
22
+ # Create simple type validators
23
+ [
24
+ [ 'array', Array ],
25
+ [ 'numeric', Numeric ],
26
+ [ 'string', String ],
27
+ [ 'time', Time ]
28
+ ].each { |name, klass| HashValidator.append_validator(HashValidator::Validator::SimpleTypeValidator.new(name, klass)) }
@@ -0,0 +1,3 @@
1
+ module HashValidator
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,149 @@
1
+ require 'spec_helper'
2
+
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
+ validate({ v: '' }, { v: {} }).valid?.should be_false
8
+ end
9
+
10
+ it 'should validate string' do
11
+ validate({ v: 'test' }, { v: 'string' }).valid?.should be_true
12
+ validate({ v: 123456 }, { v: 'string' }).valid?.should be_false
13
+ end
14
+
15
+ it 'should validate numeric' do
16
+ validate({ v: 1234 }, { v: 'numeric' }).valid?.should be_true
17
+ validate({ v: '12' }, { v: 'numeric' }).valid?.should be_false
18
+ end
19
+
20
+ it 'should validate array' do
21
+ validate({ v: [ 1,2,3 ] }, { v: 'array' }).valid?.should be_true
22
+ validate({ v: ' 1,2,3 ' }, { v: 'array' }).valid?.should be_false
23
+ end
24
+
25
+ it 'should validate time' do
26
+ validate({ v: Time.now }, { v: 'time' }).valid?.should be_true
27
+ validate({ v: '2013-04-12 13:18:05 +0930' }, { v: 'time' }).valid?.should be_false
28
+ end
29
+ end
30
+
31
+ describe 'full validations' do
32
+ let(:empty_hash) {{}}
33
+
34
+ let(:simple_hash) {{
35
+ foo: 1,
36
+ bar: 'baz'
37
+ }}
38
+
39
+ let(:invalid_simple_hash) {{
40
+ foo: 1,
41
+ bar: 2
42
+ }}
43
+
44
+ let(:complex_hash) {{
45
+ foo: 1,
46
+ bar: 'baz',
47
+ user: {
48
+ first_name: 'James',
49
+ last_name: 'Brooks',
50
+ age: 27,
51
+ likes: [ 'Ruby', 'Kendo', 'Board Games' ]
52
+ }
53
+ }}
54
+
55
+ let(:invalid_complex_hash) {{
56
+ foo: 1,
57
+ bar: 2,
58
+ user: {
59
+ first_name: 'James',
60
+ last_name: 'Brooks',
61
+ likes: 'Ruby, Kendo, Board Games'
62
+ }
63
+ }}
64
+
65
+ describe 'no validations' do
66
+ let(:validations) {{}}
67
+
68
+ it 'should validate an empty hash' do
69
+ v = validate(empty_hash, validations)
70
+ v.valid?.should be_true
71
+ v.errors.should be_empty
72
+ end
73
+
74
+ it 'should validate a simple hash' do
75
+ v = validate(simple_hash, validations)
76
+ v.valid?.should be_true
77
+ v.errors.should be_empty
78
+ end
79
+
80
+ it 'should validate a simple hash 2' do
81
+ v = validate(invalid_simple_hash, validations)
82
+ v.valid?.should be_true
83
+ v.errors.should be_empty
84
+ end
85
+
86
+ it 'should validate a complex hash' do
87
+ v = validate(complex_hash, validations)
88
+ v.valid?.should be_true
89
+ v.errors.should be_empty
90
+ end
91
+
92
+ it 'should validate a complex hash 2' do
93
+ v = validate(invalid_complex_hash, validations)
94
+ v.valid?.should be_true
95
+ v.errors.should be_empty
96
+ end
97
+ end
98
+
99
+ describe 'simple validations' do
100
+ let(:validations) {{ foo: 'numeric', bar: 'string' }}
101
+
102
+ it 'should not validate an empty hash (stating missing with required)' do
103
+ v = validate(empty_hash, validations)
104
+ v.valid?.should be_false
105
+ v.errors.should eq({ foo: 'numeric required', bar: 'string required' })
106
+ end
107
+
108
+ it 'should validate a simple hash' do
109
+ v = validate(simple_hash, validations)
110
+ v.valid?.should be_true
111
+ v.errors.should be_empty
112
+ end
113
+
114
+ it 'should not validate a simple hash 2' do
115
+ v = validate(invalid_simple_hash, validations)
116
+ v.valid?.should be_false
117
+ v.errors.should eq({ bar: 'should be string' })
118
+ end
119
+
120
+ it 'should validate a complex hash' do
121
+ v = validate(complex_hash, validations)
122
+ v.valid?.should be_true
123
+ v.errors.should be_empty
124
+ end
125
+
126
+ it 'should not validate a complex hash 2' do
127
+ v = validate(invalid_complex_hash, validations)
128
+ v.valid?.should be_false
129
+ v.errors.should eq({ bar: 'should be string' })
130
+ end
131
+ end
132
+
133
+ describe 'nested validations' do
134
+ let(:validations) {{ foo: 'numeric', bar: 'string', user: { first_name: 'string', age: 'numeric', likes: 'array' } }}
135
+
136
+ it 'should validate a complex hash' do
137
+ v = validate(complex_hash, validations)
138
+ v.valid?.should be_true
139
+ v.errors.should be_empty
140
+ end
141
+
142
+ it 'should not validate a complex hash 2' do
143
+ v = validate(invalid_complex_hash, validations)
144
+ v.valid?.should be_false
145
+ v.errors.should eq({ bar: 'should be string', user: { age: 'numeric required', likes: 'should be array' } })
146
+ end
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,5 @@
1
+ module HashValidatorSpecHelper
2
+ def validate(hash, validations)
3
+ HashValidator.validate(hash, validations)
4
+ end
5
+ end
@@ -0,0 +1,14 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'hash_validator'
4
+ require 'hash_validator_spec_helper'
5
+
6
+ RSpec.configure do |config|
7
+ config.treat_symbols_as_metadata_keys_with_true_values = true
8
+ config.run_all_when_everything_filtered = true
9
+ config.filter_run :focus
10
+
11
+ config.order = 'random'
12
+
13
+ config.include HashValidatorSpecHelper
14
+ end
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hash_validator
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - James Brooks
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-04-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: 2.13.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 2.13.0
55
+ description: Ruby library to validate hashes (Hash) against user-defined requirements
56
+ email:
57
+ - james@gooddogdesign.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - .gitignore
63
+ - .rspec
64
+ - .travis.yml
65
+ - Gemfile
66
+ - LICENSE.txt
67
+ - README.md
68
+ - Rakefile
69
+ - hash_validator.gemspec
70
+ - lib/hash_validator.rb
71
+ - lib/hash_validator/base.rb
72
+ - lib/hash_validator/validators.rb
73
+ - lib/hash_validator/validators/base.rb
74
+ - lib/hash_validator/validators/hash_validator.rb
75
+ - lib/hash_validator/validators/simple_type_validator.rb
76
+ - lib/hash_validator/version.rb
77
+ - spec/hash_validator_spec.rb
78
+ - spec/hash_validator_spec_helper.rb
79
+ - spec/spec_helper.rb
80
+ homepage: https://github.com/JamesBrooks/hash_validator
81
+ licenses:
82
+ - MIT
83
+ metadata: {}
84
+ post_install_message:
85
+ rdoc_options: []
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - '>='
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ requirements: []
99
+ rubyforge_project:
100
+ rubygems_version: 2.0.0
101
+ signing_key:
102
+ specification_version: 4
103
+ summary: Ruby library to validate hashes (Hash) against user-defined requirements
104
+ test_files:
105
+ - spec/hash_validator_spec.rb
106
+ - spec/hash_validator_spec_helper.rb
107
+ - spec/spec_helper.rb