hash_control 0.1.2
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 +7 -0
- data/.gitignore +2 -0
- data/.rspec +3 -0
- data/.travis.yml +7 -0
- data/Gemfile +7 -0
- data/LICENSE +20 -0
- data/Makefile +15 -0
- data/README.md +91 -0
- data/hash_control.gemspec +21 -0
- data/lib/hash_control/model.rb +126 -0
- data/lib/hash_control/validator.rb +115 -0
- data/lib/hash_control/version.rb +3 -0
- data/lib/hash_control.rb +3 -0
- data/spec/lib/hash_control/model_spec.rb +96 -0
- data/spec/lib/hash_control/validator_spec.rb +83 -0
- metadata +72 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6c58ba9b45b5b93680cc8d22d8dd859b355bafd3
|
4
|
+
data.tar.gz: c98ed21ba6469980f703b23f2eefeccdd6f2f8f0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c0bf551ed0f381f37b44fc87d922ca5aec7bd16f7d8839388e58c557528f69110ea962125e991608fd35a0d9abb4ca149426a755c9cee5b13df6c7f9c8188504
|
7
|
+
data.tar.gz: e72d077a10b5161b67637ad9602df132cb753283db5b5bf6d006f172783f538ac8f6c2b56f24c06496cd2f437bd7fd6b175ec21f7e01e98e372cc17d137c69f8
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2014-2015 Sean Zhu
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Makefile
ADDED
data/README.md
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
# HashControl
|
2
|
+
|
3
|
+
[](https://travis-ci.org/szhu/hashcontrol)
|
4
|
+
[](https://codeclimate.com/github/szhu/hashcontrol)
|
5
|
+
|
6
|
+
```shell
|
7
|
+
gem install hash_control
|
8
|
+
```
|
9
|
+
|
10
|
+
This Ruby library provides some conveniences for using and manipulating hash-like data.
|
11
|
+
|
12
|
+
## Features
|
13
|
+
|
14
|
+
`HashControl::Model` is a class with
|
15
|
+
|
16
|
+
- validation checking
|
17
|
+
- getting and setting properties with both `[]` and accessor methods
|
18
|
+
- setter methods can be omitted to prevent mutation
|
19
|
+
- [AwesomePrint](https://github.com/michaeldv/awesome_print) support
|
20
|
+
|
21
|
+
Want just a single-use validator? Use `HashControl::Validator`.
|
22
|
+
|
23
|
+
## Examples
|
24
|
+
|
25
|
+
### Model
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
require 'hash_control'
|
29
|
+
class Comment
|
30
|
+
include ::HashControl::Model
|
31
|
+
require_key :author, :body, :date
|
32
|
+
permit_key :image
|
33
|
+
end
|
34
|
+
|
35
|
+
require 'hash_control'
|
36
|
+
class Something
|
37
|
+
include ::HashControl::Model
|
38
|
+
require_key :id
|
39
|
+
permit_all_keys
|
40
|
+
end
|
41
|
+
|
42
|
+
Comment.new(author: 'me', body: 'interesting stuff', date: Time.now)
|
43
|
+
|
44
|
+
Comment.new(body: "this ain't gonna fly")
|
45
|
+
# ArgumentError: extra params [:extra]
|
46
|
+
# in {:body=>"this ain't gonna fly", :author=>"me", :date=>2014-01-01 00:00:00 -0000, :extra=>"hullo"}
|
47
|
+
|
48
|
+
Something.new(body: "this, however, will")
|
49
|
+
# ArgumentError: required params [:id] missing
|
50
|
+
# in {:body=>"this, however, will"}
|
51
|
+
|
52
|
+
Something.new(id: 1, body: "oops my bad")
|
53
|
+
```
|
54
|
+
|
55
|
+
### Validator
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
require 'hash_control'
|
59
|
+
get_request = {
|
60
|
+
get: '/api/article/23/comment/34/show'
|
61
|
+
}
|
62
|
+
post_request = {
|
63
|
+
post: '/api/article/23/comment/34/update',
|
64
|
+
body: {
|
65
|
+
date: Time.new,
|
66
|
+
body: 'hullo',
|
67
|
+
meta: 'fsdkfsifhdsfsdhkj'
|
68
|
+
}
|
69
|
+
}
|
70
|
+
validator = ::HashControl::Validator.new(post_request)
|
71
|
+
validator.require(:post).permit(:body).only
|
72
|
+
# `permit` marks keys as allowed but doesn't do any verification
|
73
|
+
# `only` ensures no other keys are present
|
74
|
+
|
75
|
+
class CustomValidator < ::HashControl::Validator
|
76
|
+
def validate_request
|
77
|
+
require_one_of(:get, :post)
|
78
|
+
end
|
79
|
+
|
80
|
+
def validate_get_request
|
81
|
+
validate_request.only
|
82
|
+
end
|
83
|
+
|
84
|
+
def validate_post_request
|
85
|
+
validate_request.permit(:body).only
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
CustomValidator.new(get_request).validate_get_request
|
90
|
+
CustomValidator.new(post_request).validate_post_request
|
91
|
+
```
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require './lib/hash_control/version'
|
2
|
+
|
3
|
+
Gem::Specification.new do |gem|
|
4
|
+
gem.name = File.basename(ARGV[1], '.gemspec')
|
5
|
+
gem.summary = 'Conveniently validating and manipulating hash-like data.'
|
6
|
+
gem.description = <<-END
|
7
|
+
Provides some conveniences for validating and manipulating hash-like data.
|
8
|
+
END
|
9
|
+
|
10
|
+
gem.version = ::HashControl::VERSION
|
11
|
+
gem.date = '2014-08-22'
|
12
|
+
|
13
|
+
gem.homepage = 'https://github.com/szhu/hashcontrol'
|
14
|
+
gem.authors = ['Sean Zhu']
|
15
|
+
gem.email = 'interestinglythere@gmail.com'
|
16
|
+
gem.license = 'MIT'
|
17
|
+
|
18
|
+
gem.add_dependency 'activesupport', '~> 4.0'
|
19
|
+
gem.files = `git ls-files`.split($RS)
|
20
|
+
gem.require_paths = ['lib']
|
21
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
2
|
+
require 'active_support/hash_with_indifferent_access'
|
3
|
+
require_relative 'validator'
|
4
|
+
|
5
|
+
module HashControl
|
6
|
+
# An hash-like type that requires certain keys to be defined
|
7
|
+
module Model
|
8
|
+
def initialize(hash = {})
|
9
|
+
@hash = ::ActiveSupport::HashWithIndifferentAccess.new(hash)
|
10
|
+
initialize_model if self.class.method_defined? :initialize_model
|
11
|
+
hash_validator = validate_default
|
12
|
+
validate(hash_validator) if self.class.method_defined? :validate
|
13
|
+
end
|
14
|
+
|
15
|
+
def symbolized_hash
|
16
|
+
@hash.symbolize_keys
|
17
|
+
end
|
18
|
+
|
19
|
+
def slice(*keys)
|
20
|
+
@symbolized_hash.select { |key, _| keys.include? key.to_sym }
|
21
|
+
end
|
22
|
+
|
23
|
+
def [](name)
|
24
|
+
@hash[name]
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def validate_default
|
30
|
+
hash_validator = Validator.new(@hash)
|
31
|
+
hash_validator.require(*self.class.required_keys)
|
32
|
+
unless self.class.permitted_keys == :all
|
33
|
+
hash_validator.permit(*self.class.permitted_keys).only
|
34
|
+
end
|
35
|
+
hash_validator
|
36
|
+
end
|
37
|
+
|
38
|
+
module ClassMethods
|
39
|
+
def initialize_class
|
40
|
+
instance_variable_set(:@required_keys, Set.new)
|
41
|
+
instance_variable_set(:@permitted_keys, Set.new)
|
42
|
+
end
|
43
|
+
attr_reader :required_keys, :permitted_keys
|
44
|
+
|
45
|
+
def permit_all_keys
|
46
|
+
@permitted_keys = :all
|
47
|
+
end
|
48
|
+
|
49
|
+
def require_key(*keys)
|
50
|
+
keys.each { |key| key_accessor(key) }
|
51
|
+
required_keys.merge keys
|
52
|
+
end
|
53
|
+
|
54
|
+
def permit_key(*keys)
|
55
|
+
keys.each { |key| key_accessor(key) }
|
56
|
+
permitted_keys.merge keys
|
57
|
+
end
|
58
|
+
|
59
|
+
def key_accessor(name)
|
60
|
+
name = name.to_sym
|
61
|
+
return if self.respond_to?(name)
|
62
|
+
class_eval do
|
63
|
+
define_method(name) { @hash[name] }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.included(base)
|
69
|
+
base.extend ClassMethods
|
70
|
+
base.initialize_class
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Allow setting
|
75
|
+
module WritableModel
|
76
|
+
include Model
|
77
|
+
|
78
|
+
module ClassMethods
|
79
|
+
def key_accessor(name)
|
80
|
+
name = name.to_sym
|
81
|
+
return if self.respond_to?(name)
|
82
|
+
class_eval do
|
83
|
+
define_method(name) { @hash[name] }
|
84
|
+
define_method("#{name}=") { |x| @hash[name] = x }
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def []=(name, x)
|
90
|
+
@hash[name] = x
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.included(base)
|
94
|
+
Model.included(base)
|
95
|
+
base.extend ClassMethods
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# Add extra I/O
|
100
|
+
# Placed in a separate block for sake of clarity
|
101
|
+
module Model
|
102
|
+
# JSON support
|
103
|
+
module ClassMethods
|
104
|
+
def json_create(hash_as_json)
|
105
|
+
require 'json'
|
106
|
+
hash = JSON.parse hash_as_json
|
107
|
+
new hash
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def to_json
|
112
|
+
require 'json'
|
113
|
+
@hash.to_json
|
114
|
+
end
|
115
|
+
|
116
|
+
def as_json(_opts = {})
|
117
|
+
symbolized_hash
|
118
|
+
end
|
119
|
+
|
120
|
+
# AwesomePrint support
|
121
|
+
def ai(options)
|
122
|
+
require 'awesome_print'
|
123
|
+
AwesomePrint::Inspector.new(options).awesome(symbolized_hash)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'active_support/hash_with_indifferent_access'
|
2
|
+
require 'active_support/inflector'
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
module HashControl
|
6
|
+
class Validator
|
7
|
+
def initialize(hash, opts = {})
|
8
|
+
if hash.is_a? ::ActiveSupport::HashWithIndifferentAccess
|
9
|
+
@hash = hash
|
10
|
+
else
|
11
|
+
@hash = ::ActiveSupport::HashWithIndifferentAccess.new(hash)
|
12
|
+
end
|
13
|
+
@error_class = opts[:raising] || ArgumentError
|
14
|
+
@term = opts[:term] || 'param'
|
15
|
+
@string_keys = opts[:string_keys] || false
|
16
|
+
@permitted_keys = Set.new
|
17
|
+
end
|
18
|
+
|
19
|
+
# Specifies keys that must exist
|
20
|
+
def require(*keys)
|
21
|
+
permitted_keys.merge keys
|
22
|
+
required_keys = keys.to_set
|
23
|
+
unless (missing_keys = required_keys - hash_keys).empty?
|
24
|
+
error "required #{terms} #{missing_keys.to_a} missing" + postscript
|
25
|
+
end
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
def require_n_of(n, *keys)
|
30
|
+
permitted_keys.merge keys
|
31
|
+
required_keys = keys.to_set
|
32
|
+
if (missing_keys = required_keys - hash_keys).length > n
|
33
|
+
error "#{n} or more #{terms} in #{missing_keys.to_a} must be given" + postscript
|
34
|
+
end
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
def require_one_of(*keys)
|
39
|
+
require_n_of(1, *keys)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Specifies keys that can exist with no further restrictions
|
43
|
+
# Does no checking on its own
|
44
|
+
def permit(*keys)
|
45
|
+
permitted_keys.merge keys
|
46
|
+
self
|
47
|
+
end
|
48
|
+
|
49
|
+
# Checks that only the the previously mentioned keys exist
|
50
|
+
# In Rails, `permit' will do this as well, but having this as a separate
|
51
|
+
# option allows for specifying permit not at the beginning of the chain
|
52
|
+
def only
|
53
|
+
unless (extra_keys = hash_keys - permitted_keys).empty?
|
54
|
+
error "extra #{terms} #{extra_keys.to_a}" + postscript
|
55
|
+
end
|
56
|
+
self
|
57
|
+
end
|
58
|
+
|
59
|
+
# Similar to Rails' `permit' method.
|
60
|
+
def permit_only(*keys)
|
61
|
+
permit(*keys).only
|
62
|
+
end
|
63
|
+
|
64
|
+
def int(*keys)
|
65
|
+
permitted_keys.merge keys
|
66
|
+
keys.each do |key|
|
67
|
+
next if hash[key].is_a? Integer
|
68
|
+
error "#{term} #{key.inspect} must be integer but was #{hash[key].inspect}" + postscript
|
69
|
+
end
|
70
|
+
self
|
71
|
+
end
|
72
|
+
|
73
|
+
def int_or_nil(*keys)
|
74
|
+
permitted_keys.merge keys
|
75
|
+
keys.each do |key|
|
76
|
+
next if hash[key].nil? || hash[key].is_a?(Integer)
|
77
|
+
error "#{term} #{key.inspect} must be integer but was #{hash[key].inspect}" + postscript
|
78
|
+
end
|
79
|
+
self
|
80
|
+
end
|
81
|
+
|
82
|
+
def not_nil(*keys)
|
83
|
+
permitted_keys.merge keys
|
84
|
+
keys.each do |key|
|
85
|
+
next unless hash[key].nil?
|
86
|
+
error "#{term} #{key.inspect} is nil" + postscript
|
87
|
+
end
|
88
|
+
self
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def hash
|
94
|
+
@string_keys ? @hash : @hash.symbolize_keys
|
95
|
+
end
|
96
|
+
|
97
|
+
def hash_keys
|
98
|
+
(@string_keys ? @hash.keys : @hash.keys.map(&:to_sym)).to_set
|
99
|
+
end
|
100
|
+
|
101
|
+
attr_reader :permitted_keys, :term
|
102
|
+
|
103
|
+
def error(message)
|
104
|
+
raise @error_class, message
|
105
|
+
end
|
106
|
+
|
107
|
+
def postscript
|
108
|
+
"\n\tin #{hash.inspect}"
|
109
|
+
end
|
110
|
+
|
111
|
+
def terms
|
112
|
+
@terms ||= term.pluralize
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
data/lib/hash_control.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'hash_control/model'
|
2
|
+
|
3
|
+
describe HashControl::Model do
|
4
|
+
before :all do
|
5
|
+
class Comment
|
6
|
+
include ::HashControl::Model
|
7
|
+
require_key :author, :body, :date
|
8
|
+
permit_key :image
|
9
|
+
end
|
10
|
+
|
11
|
+
class Something
|
12
|
+
include ::HashControl::Model
|
13
|
+
require_key :id
|
14
|
+
permit_all_keys
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "making an instance should error if it" do
|
19
|
+
it "does not permit all keys and has extra params" do
|
20
|
+
expect {
|
21
|
+
Comment.new(body: "this ain't gonna fly", author: 'me', date: Time.now, extra: 'hullo')
|
22
|
+
}.to raise_error(ArgumentError)
|
23
|
+
# ArgumentError: extra params [:extra]
|
24
|
+
# in {:body=>"this ain't gonna fly", :author=>"me", :date=>2014-01-01 00:00:00 -0000, :extra=>"hullo"}
|
25
|
+
end
|
26
|
+
|
27
|
+
it "is missing required params" do
|
28
|
+
expect {
|
29
|
+
Something.new(body: "this won't either")
|
30
|
+
}.to raise_error(ArgumentError)
|
31
|
+
# ArgumentError: required params [:id] missing
|
32
|
+
# in {:body=>"this won't either"}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "a valid model" do
|
37
|
+
describe "that permits only certain keys" do
|
38
|
+
before :all do
|
39
|
+
@comment = Comment.new(author: 'me', body: 'interesting stuff', date: Time.now)
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "can use methods to access" do
|
43
|
+
it "explicitly required and permitted keys" do
|
44
|
+
expect(@comment.author).to eq('me')
|
45
|
+
expect(@comment.body).to eq('interesting stuff')
|
46
|
+
expect(@comment.date.class).to eq(Time)
|
47
|
+
expect(@comment.image).to eq(nil)
|
48
|
+
end
|
49
|
+
it "not other keys" do
|
50
|
+
expect{@comment.nonexistent}.to raise_error(NoMethodError)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "can use [] (using both string and symbol) to access" do
|
55
|
+
it "all keys regardless of whether they exist" do
|
56
|
+
expect(@comment['author']).to eq('me')
|
57
|
+
expect(@comment[:author]).to eq('me')
|
58
|
+
expect(@comment['image']).to eq(nil)
|
59
|
+
expect(@comment[:image]).to eq(nil)
|
60
|
+
expect(@comment['nonexistent']).to eq(nil)
|
61
|
+
expect(@comment[:nonexistent]).to eq(nil)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "that permits all keys" do
|
68
|
+
before :all do
|
69
|
+
@something = Something.new(id: 1, body: "heh")
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "can use methods to access" do
|
73
|
+
it "explicitly required and permitted keys" do
|
74
|
+
expect(@something.id).to eq(1)
|
75
|
+
end
|
76
|
+
it "not implicitly-permitted keys" do
|
77
|
+
expect{@something.body}.to raise_error(NoMethodError)
|
78
|
+
expect{@something.nonexistent}.to raise_error(NoMethodError)
|
79
|
+
end
|
80
|
+
it "not other keys" do
|
81
|
+
expect{@something.body}.to raise_error(NoMethodError)
|
82
|
+
expect{@something.nonexistent}.to raise_error(NoMethodError)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "can use [] (using both string and symbol) to access" do
|
87
|
+
it "all keys regardless of whether they exist" do
|
88
|
+
expect(@something['body']).to eq('heh')
|
89
|
+
expect(@something[:body]).to eq('heh')
|
90
|
+
expect(@something['nonexistent']).to eq(nil)
|
91
|
+
expect(@something[:nonexistent]).to eq(nil)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'hash_control/validator'
|
2
|
+
|
3
|
+
describe HashControl::Validator do
|
4
|
+
def validate(hash)
|
5
|
+
::HashControl::Validator.new(hash)
|
6
|
+
end
|
7
|
+
|
8
|
+
before :all do
|
9
|
+
@empty = {
|
10
|
+
}
|
11
|
+
@get_request = {
|
12
|
+
get: '/api/article/23/comment/34/show'
|
13
|
+
}
|
14
|
+
@post_request = {
|
15
|
+
post: '/api/article/23/comment/34/update',
|
16
|
+
body: {
|
17
|
+
date: Time.new,
|
18
|
+
body: 'hullo',
|
19
|
+
meta: 'fsdkfsifhdsfsdhkj'
|
20
|
+
}
|
21
|
+
}
|
22
|
+
@not_allowed_but_currently_ok = {
|
23
|
+
get: 'something',
|
24
|
+
post: 'something_else'
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "when used as its own class," do
|
29
|
+
# `require` ensures certain keys are present
|
30
|
+
it "require should work properly" do
|
31
|
+
expect{ validate(@post_request).require(:post) }.not_to raise_error
|
32
|
+
expect{ validate(@post_request).require(:body) }.not_to raise_error
|
33
|
+
expect{ validate(@post_request).require(:post, :body) }.not_to raise_error
|
34
|
+
expect{ validate(@post_request).require(:nonexistent) }.to raise_error(ArgumentError)
|
35
|
+
end
|
36
|
+
|
37
|
+
# `require_n_of` ensures at least n of certain keys are present
|
38
|
+
it "require_n_of should work properly" do
|
39
|
+
expect{ validate(@post_request).require_n_of(2, :post, :body) }.not_to raise_error
|
40
|
+
end
|
41
|
+
|
42
|
+
# `permit` marks keys as allowed but doesn't do any verification
|
43
|
+
it "permit should work properly" do
|
44
|
+
expect{ validate(@post_request).permit(:body) }.not_to raise_error
|
45
|
+
expect{ validate(@post_request).permit(:nonexistent) }.not_to raise_error
|
46
|
+
end
|
47
|
+
|
48
|
+
# `only` ensures no other keys are present
|
49
|
+
it "only should work properly" do
|
50
|
+
expect{ validate(@post_request).only }.to raise_error(ArgumentError)
|
51
|
+
expect{ validate(@post_request).require(:post).only }.to raise_error(ArgumentError)
|
52
|
+
expect{ validate(@post_request).require(:post).permit(:body).only }.not_to raise_error
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "when subclassed," do
|
57
|
+
before :all do
|
58
|
+
class CustomValidator < ::HashControl::Validator
|
59
|
+
def validate_request
|
60
|
+
require_one_of(:get, :post)
|
61
|
+
end
|
62
|
+
|
63
|
+
def validate_get_request
|
64
|
+
validate_request.only
|
65
|
+
end
|
66
|
+
|
67
|
+
def validate_post_request
|
68
|
+
validate_request.permit(:body).only
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should work properly for allowed hashes" do
|
74
|
+
expect{ CustomValidator.new(@get_request).validate_get_request }.not_to raise_error
|
75
|
+
expect{ CustomValidator.new(@post_request).validate_post_request }.not_to raise_error
|
76
|
+
expect{ CustomValidator.new(@not_allowed_but_currently_ok).validate_post_request }.not_to raise_error
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should work properly for invalid hashes" do
|
80
|
+
expect{ CustomValidator.new(@empty).validate_get_request }.to raise_error(ArgumentError)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
metadata
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hash_control
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sean Zhu
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-08-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.0'
|
27
|
+
description: |2
|
28
|
+
Provides some conveniences for validating and manipulating hash-like data.
|
29
|
+
email: interestinglythere@gmail.com
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- ".gitignore"
|
35
|
+
- ".rspec"
|
36
|
+
- ".travis.yml"
|
37
|
+
- Gemfile
|
38
|
+
- LICENSE
|
39
|
+
- Makefile
|
40
|
+
- README.md
|
41
|
+
- hash_control.gemspec
|
42
|
+
- lib/hash_control.rb
|
43
|
+
- lib/hash_control/model.rb
|
44
|
+
- lib/hash_control/validator.rb
|
45
|
+
- lib/hash_control/version.rb
|
46
|
+
- spec/lib/hash_control/model_spec.rb
|
47
|
+
- spec/lib/hash_control/validator_spec.rb
|
48
|
+
homepage: https://github.com/szhu/hashcontrol
|
49
|
+
licenses:
|
50
|
+
- MIT
|
51
|
+
metadata: {}
|
52
|
+
post_install_message:
|
53
|
+
rdoc_options: []
|
54
|
+
require_paths:
|
55
|
+
- lib
|
56
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
requirements: []
|
67
|
+
rubyforge_project:
|
68
|
+
rubygems_version: 2.2.2
|
69
|
+
signing_key:
|
70
|
+
specification_version: 4
|
71
|
+
summary: Conveniently validating and manipulating hash-like data.
|
72
|
+
test_files: []
|