yas 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.markdown +56 -26
- data/lib/yas/ext/attribute.rb +40 -28
- data/lib/yas/ext/rename.rb +6 -6
- data/lib/yas/ext/symbolize.rb +30 -0
- data/lib/yas/schema.rb +2 -1
- data/lib/yas/version.rb +1 -1
- data/lib/yas.rb +1 -2
- data/test/ext/test_attribute.rb +15 -1
- data/test/ext/test_rename.rb +4 -1
- data/test/ext/test_symbolize.rb +23 -0
- data/test/test_schema.rb +23 -0
- metadata +4 -3
- data/lib/yas/helper.rb +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 14bc3ae92e4d7b9e86b4231edfb5f44cb5d04e1f
|
4
|
+
data.tar.gz: 149294a84a65f4eb2bc726c8cdbf41fe6c16593c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 04efb2cbe5b897de52da85c02244b127b2ba65bc512ba8e510c7b1a516814cb8f37a71bdda8b62cdd3b94898ef262503754428b138346260a2494d30d937ead4
|
7
|
+
data.tar.gz: 69c588d7f01c2f2a2a96ba37fdebcc5b82a78beb6e1ef3c85586e70b782b988bbea57f50128d58bcd4ec64a70ccfb7c027cab7d759aeede50cf01131b45bba83
|
data/README.markdown
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# YAS
|
2
2
|
|
3
|
-
YAS (Yet Another Schema) is an extensible hash validator for Ruby.
|
3
|
+
YAS (Yet Another Schema) is an extensible hash validator for Ruby used to maintain hash integrity.
|
4
4
|
Using YAS, you can enforce a specific key to be required, rename them, perform automatic type conversion, and other goodies.
|
5
5
|
|
6
6
|
|
@@ -14,39 +14,34 @@ Using YAS, you can enforce a specific key to be required, rename them, perform a
|
|
14
14
|
require 'yas'
|
15
15
|
|
16
16
|
class MySchema < YAS::Schema
|
17
|
-
rename :
|
17
|
+
rename :bar => :foo
|
18
18
|
end
|
19
19
|
|
20
20
|
h = { bar: "value" }
|
21
21
|
h.validate! MySchema
|
22
|
-
|
23
|
-
|
22
|
+
h[:foo] # "value"
|
23
|
+
h[:bar] # nil
|
24
24
|
|
25
25
|
|
26
26
|
## Extensions
|
27
27
|
|
28
|
-
You can extend the behavior of YAS by writing your own custom extensions
|
28
|
+
You can extend the behavior of YAS by writing your own custom extensions.
|
29
|
+
`YAS::Schema` already comes with a set of awesome default extensions that you can immediately use.
|
30
|
+
Optionally, you may also use `YAS::SchemaBase` if you want to start off from a clean slate.
|
29
31
|
|
30
|
-
* `attribute name, &block` or `key name, &block`
|
31
32
|
|
32
|
-
|
33
|
+
### Default Extensions
|
33
34
|
|
34
|
-
* `rename`
|
35
35
|
|
36
|
-
|
36
|
+
#### Attribute
|
37
37
|
|
38
|
-
|
38
|
+
Declares an attribute/key with various requirements.
|
39
|
+
The Attribute extension allows you to specify certain requirements/restrictions for a given key.
|
39
40
|
|
40
|
-
|
41
|
+
attribute name, &block
|
42
|
+
key name, &block
|
41
43
|
|
42
|
-
|
43
|
-
|
44
|
-
Provide a set of keys that you only care to see.
|
45
|
-
|
46
|
-
|
47
|
-
### Attribute Extension
|
48
|
-
|
49
|
-
The Attribute extension allows you to specify certain requirements/restrictions for a given key:
|
44
|
+
Example:
|
50
45
|
|
51
46
|
class MySchema < YAS::Schema
|
52
47
|
key :email do
|
@@ -71,7 +66,7 @@ List of directives you can use:
|
|
71
66
|
|
72
67
|
* `type(T)`
|
73
68
|
|
74
|
-
Sets the type of this key. Will perform type check if specified. Can be nested if type is a YAS::Schema
|
69
|
+
Sets the type of this key. Will perform type check if specified. Can be nested if type is a `YAS::Schema`!
|
75
70
|
|
76
71
|
* `auto_convert`
|
77
72
|
|
@@ -81,14 +76,24 @@ List of directives you can use:
|
|
81
76
|
|
82
77
|
Runs the block to set the default value for this key, if it's missing or nil.
|
83
78
|
|
79
|
+
* `alter(&block)`
|
80
|
+
|
81
|
+
Adjust the value of this key. Can be useful if you want to enforce certain formatting, such as upper/lowercase, unique arrays, etc.
|
82
|
+
Value returned by block will be used as the new value for this key, which then gets validated by the `validate_value` block.
|
83
|
+
|
84
84
|
* `validate_value(&block)`
|
85
85
|
|
86
|
-
Custom validation method to check the value of a key. This is useful in cases where you only want certain values to be stored (e.g a number between 1-10 only)
|
86
|
+
Custom validation method to check the value of a key. This is useful in cases where you only want certain values to be stored (e.g a number between 1-10 only).
|
87
|
+
Return true to indicate value passes validation, false for fail.
|
87
88
|
|
88
89
|
|
89
|
-
|
90
|
+
#### Rename
|
90
91
|
|
91
|
-
Using `rename` to rename keys.
|
92
|
+
Using `rename` to rename keys.
|
93
|
+
|
94
|
+
rename :from => :to
|
95
|
+
|
96
|
+
Example:
|
92
97
|
|
93
98
|
class UserSchema < YAS::Schema
|
94
99
|
rename :username => :nickname
|
@@ -98,9 +103,13 @@ Using `rename` to rename keys. Useful to maintain hash integrity.
|
|
98
103
|
hash[:nickname] # 'jdoe'
|
99
104
|
|
100
105
|
|
101
|
-
|
106
|
+
#### Migrate
|
107
|
+
|
108
|
+
Migrate the value of a key. This is useful if you have keys whose values are in the old format and you want to convert them to the new format.
|
102
109
|
|
103
|
-
|
110
|
+
migrate :key, &block
|
111
|
+
|
112
|
+
Example:
|
104
113
|
|
105
114
|
class UserSchema < YAS::Schema
|
106
115
|
migrate :nicknames do |v|
|
@@ -112,10 +121,14 @@ You can also migrate the values. This is useful if you have hash whose values ar
|
|
112
121
|
hash[:nicknames] # ['jdoe']
|
113
122
|
|
114
123
|
|
115
|
-
|
124
|
+
#### Whitelist
|
116
125
|
|
117
126
|
Whitelist allows you to remove unneeded keys.
|
118
127
|
|
128
|
+
whitelist [keys]
|
129
|
+
|
130
|
+
Example:
|
131
|
+
|
119
132
|
class UserSchema < YAS::Schema
|
120
133
|
whitelist :name, :address
|
121
134
|
end
|
@@ -125,3 +138,20 @@ Whitelist allows you to remove unneeded keys.
|
|
125
138
|
hash[:address] # ['123 Main St']
|
126
139
|
hash[:phone] # nil
|
127
140
|
hash[:comment] # nil
|
141
|
+
|
142
|
+
|
143
|
+
#### Symbolize
|
144
|
+
|
145
|
+
Symbolize keys in your hash.
|
146
|
+
This does not perform deep symbolize. See nested Attribute validation if you want deep symbolize.
|
147
|
+
|
148
|
+
symbolize true|false
|
149
|
+
|
150
|
+
Example:
|
151
|
+
|
152
|
+
class UserSchema < YAS::Schema
|
153
|
+
symbolize true
|
154
|
+
end
|
155
|
+
hash = { 'name' => 'jdoe', 'address' => '123 Main St' }
|
156
|
+
hash.validate!(UserSchema)
|
157
|
+
hash[:name] # ['jdoe']
|
data/lib/yas/ext/attribute.rb
CHANGED
@@ -6,7 +6,6 @@ class YAS::AttributeExt
|
|
6
6
|
module ClassMethods
|
7
7
|
|
8
8
|
def key attr, &block
|
9
|
-
attr = attr.to_s.to_sym
|
10
9
|
new_attr = Attribute.new(attr)
|
11
10
|
new_attr.instance_eval &block if block
|
12
11
|
attributes[attr] = new_attr
|
@@ -50,11 +49,12 @@ class YAS::AttributeExt
|
|
50
49
|
@type = nil
|
51
50
|
@auto_convert = false
|
52
51
|
@default_block = nil
|
53
|
-
@
|
52
|
+
@alter_block = nil
|
53
|
+
@validate_value_block = nil
|
54
54
|
|
55
55
|
|
56
56
|
def initialize name
|
57
|
-
@name = name
|
57
|
+
@name = name
|
58
58
|
end
|
59
59
|
|
60
60
|
|
@@ -116,33 +116,44 @@ class YAS::AttributeExt
|
|
116
116
|
# validate_value { |v| v == "John" }
|
117
117
|
#
|
118
118
|
def validate_value &block
|
119
|
-
@
|
119
|
+
@validate_value_block = block
|
120
120
|
self
|
121
121
|
end
|
122
122
|
|
123
123
|
|
124
|
-
#
|
124
|
+
# Perform adjustment to the value of this Attribute.
|
125
125
|
#
|
126
|
-
# @
|
126
|
+
# @yield [v] Value of the Attribute.
|
127
127
|
#
|
128
|
-
|
129
|
-
|
128
|
+
# @example
|
129
|
+
# alter { |v| v == "John" }
|
130
|
+
#
|
131
|
+
def alter &block
|
132
|
+
@alter_block = block
|
133
|
+
self
|
130
134
|
end
|
131
135
|
|
132
136
|
|
133
|
-
#
|
137
|
+
# Validates attribute, except the required directive.
|
138
|
+
# First it executes the {default} directive, then {auto_convert} to type,
|
139
|
+
# then {type} validation, then finally the {validate} directive.
|
134
140
|
#
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
+
# @return The final value after the validation.
|
142
|
+
#
|
143
|
+
def validate value
|
144
|
+
value = trigger_default_directive if value.nil?
|
145
|
+
trigger_validate_value_directive(trigger_alter_directive(trigger_type_directive(value)))
|
146
|
+
end
|
147
|
+
|
148
|
+
|
149
|
+
private
|
150
|
+
|
151
|
+
|
152
|
+
def trigger_default_directive
|
153
|
+
@default_block.call if has_default?
|
141
154
|
end
|
142
155
|
|
143
156
|
|
144
|
-
# Check type.
|
145
|
-
#
|
146
157
|
def trigger_type_directive value
|
147
158
|
if @type
|
148
159
|
# Run auto-conversion first.
|
@@ -162,8 +173,6 @@ class YAS::AttributeExt
|
|
162
173
|
end
|
163
174
|
|
164
175
|
|
165
|
-
# Auto convert the value
|
166
|
-
#
|
167
176
|
def trigger_auto_convert_directive value
|
168
177
|
if @auto_convert
|
169
178
|
if @type == Integer
|
@@ -184,15 +193,18 @@ class YAS::AttributeExt
|
|
184
193
|
end
|
185
194
|
|
186
195
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
def
|
194
|
-
|
195
|
-
|
196
|
+
def trigger_alter_directive value
|
197
|
+
value = @alter_block.call(value) if @alter_block
|
198
|
+
value
|
199
|
+
end
|
200
|
+
|
201
|
+
|
202
|
+
def trigger_validate_value_directive value
|
203
|
+
if @validate_value_block
|
204
|
+
raise YAS::ValidationError, "Content validation error: #{value}" unless
|
205
|
+
@validate_value_block.call(value)
|
206
|
+
end
|
207
|
+
value
|
196
208
|
end
|
197
209
|
|
198
210
|
end
|
data/lib/yas/ext/rename.rb
CHANGED
@@ -10,8 +10,7 @@ class YAS::RenameExt
|
|
10
10
|
|
11
11
|
module ClassMethods
|
12
12
|
def rename map
|
13
|
-
|
14
|
-
rename_keys.merge!(smap)
|
13
|
+
rename_keys.merge!(map)
|
15
14
|
end
|
16
15
|
|
17
16
|
def rename_keys
|
@@ -26,17 +25,18 @@ class YAS::RenameExt
|
|
26
25
|
|
27
26
|
|
28
27
|
def self.when_schema_inherited superschema, subschema
|
29
|
-
superschema.rename_keys.each do |from,
|
30
|
-
subschema.rename_keys[key] =
|
28
|
+
superschema.rename_keys.each do |from, to|
|
29
|
+
subschema.rename_keys[key] = to
|
31
30
|
end
|
32
31
|
end
|
33
32
|
|
34
33
|
|
35
34
|
def self.apply schema, hash
|
36
35
|
schema.rename_keys.each do |from, to|
|
37
|
-
hash.has_key?(from)
|
38
|
-
hash[to] = hash[from]
|
36
|
+
if hash.has_key?(from)
|
37
|
+
hash[to] = hash[from]
|
39
38
|
hash.delete(from)
|
39
|
+
end
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# Symbolize keys
|
2
|
+
#
|
3
|
+
|
4
|
+
class YAS::SymbolizeExt
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
def symbolize sym = nil
|
8
|
+
@symbolize = sym if !sym.nil? && (sym.class == TrueClass || sym.class == FalseClass)
|
9
|
+
@symbolize
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
def self.when_used schema
|
15
|
+
schema.extend ClassMethods
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
def self.when_schema_inherited superschema, subschema
|
20
|
+
subschema.symbolize(superschema.symbolize)
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
def self.apply schema, hash
|
25
|
+
hash.keys.each do |key|
|
26
|
+
hash[(key.to_sym rescue key) || key] = hash.delete(key)
|
27
|
+
end if schema.symbolize
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
data/lib/yas/schema.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
class YAS::SchemaBase
|
2
2
|
|
3
3
|
def self.use ext
|
4
|
-
raise YAS::ExtensionError, "Duplicate Extension" if exts.
|
4
|
+
raise YAS::ExtensionError, "Duplicate Extension. Extension #{ext} is already used." if exts.include?(ext)
|
5
5
|
raise YAS::ExtensionError, "Wrong Extension Format" unless ext.respond_to?(:apply) && ext.respond_to?(:when_used)
|
6
6
|
exts << ext
|
7
7
|
ext.when_used(self)
|
@@ -38,6 +38,7 @@ end
|
|
38
38
|
|
39
39
|
class YAS::Schema < YAS::SchemaBase
|
40
40
|
|
41
|
+
use YAS::SymbolizeExt
|
41
42
|
use YAS::RenameExt
|
42
43
|
use YAS::WhitelistExt
|
43
44
|
use YAS::MigrateExt
|
data/lib/yas/version.rb
CHANGED
data/lib/yas.rb
CHANGED
data/test/ext/test_attribute.rb
CHANGED
@@ -87,7 +87,14 @@ class TestAttribute < Minitest::Test
|
|
87
87
|
end
|
88
88
|
|
89
89
|
|
90
|
-
def
|
90
|
+
def test_alter
|
91
|
+
attr = Attribute.new(:batman).alter { |v| v.uniq!; v.compact!; v }
|
92
|
+
value = attr.validate(["Jim", "John", "Jim", "Kim", "Sally"])
|
93
|
+
assert_equal ["Jim", "John", "Kim", "Sally"], value
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
def test_validate_value
|
91
98
|
attr = Attribute.new(:batman).validate_value { |v| v == "John" }
|
92
99
|
assert_raises YAS::ValidationError do
|
93
100
|
attr.validate("Jim")
|
@@ -138,6 +145,11 @@ class AttributeSchema < YAS::Schema
|
|
138
145
|
auto_convert
|
139
146
|
end
|
140
147
|
|
148
|
+
key 'geo' do
|
149
|
+
type Float
|
150
|
+
auto_convert
|
151
|
+
end
|
152
|
+
|
141
153
|
end
|
142
154
|
|
143
155
|
|
@@ -157,9 +169,11 @@ class TestAttributeExt < Minitest::Test
|
|
157
169
|
hash = {
|
158
170
|
name: "someone",
|
159
171
|
number: 10,
|
172
|
+
'geo' => '10.20',
|
160
173
|
}
|
161
174
|
hash.validate! AttributeSchema
|
162
175
|
assert_equal "someone", hash[:name]
|
176
|
+
assert_equal 10.20, hash['geo']
|
163
177
|
end
|
164
178
|
|
165
179
|
|
data/test/ext/test_rename.rb
CHANGED
@@ -2,21 +2,24 @@ require './test/helper.rb'
|
|
2
2
|
|
3
3
|
class RenameSchema < YAS::Schema
|
4
4
|
rename :addr => :address
|
5
|
+
rename 'home' => 'office'
|
5
6
|
end
|
6
7
|
|
7
8
|
|
9
|
+
|
8
10
|
class TestRenameExt < Minitest::Test
|
9
11
|
|
10
12
|
def test_rename_ext
|
11
13
|
hash = {
|
12
14
|
addr: "Some address",
|
15
|
+
'home' => 'home address',
|
13
16
|
untouched: "Nothing"
|
14
17
|
}
|
15
18
|
hash.validate! RenameSchema
|
16
19
|
assert_equal "Some address", hash[:address]
|
20
|
+
assert_equal "home address", hash['office']
|
17
21
|
assert_equal "Nothing", hash[:untouched]
|
18
22
|
assert_nil hash[:addr]
|
19
|
-
assert_equal 2, hash.length
|
20
23
|
end
|
21
24
|
|
22
25
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require './test/helper.rb'
|
2
|
+
|
3
|
+
|
4
|
+
class SymbolizedSchema < YAS::Schema
|
5
|
+
symbolize true
|
6
|
+
end
|
7
|
+
|
8
|
+
|
9
|
+
class TestSymbolizeExt < Minitest::Test
|
10
|
+
|
11
|
+
def test_symbolize
|
12
|
+
hash = {
|
13
|
+
'first_name': "john",
|
14
|
+
'last_name': "doe",
|
15
|
+
}
|
16
|
+
hash.validate! SymbolizedSchema
|
17
|
+
assert_equal "john", hash[:first_name]
|
18
|
+
assert_equal "doe", hash[:last_name]
|
19
|
+
assert_nil hash['first_name']
|
20
|
+
assert_nil hash['last_name']
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
data/test/test_schema.rb
CHANGED
@@ -57,6 +57,27 @@ end
|
|
57
57
|
|
58
58
|
class TestSchema < Minitest::Test
|
59
59
|
|
60
|
+
def test_duplicate_ext
|
61
|
+
assert_raises YAS::ExtensionError do
|
62
|
+
Class.new(YAS::Schema) do
|
63
|
+
use YAS::RenameExt
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
def test_invalid_ext_format
|
70
|
+
bad_ext = Class.new do
|
71
|
+
end
|
72
|
+
|
73
|
+
assert_raises YAS::ExtensionError do
|
74
|
+
Class.new(YAS::Schema) do
|
75
|
+
use bad_ext
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
|
60
81
|
def test_validate_not_bang_does_not_overwrite_original
|
61
82
|
hash = {
|
62
83
|
names: "john",
|
@@ -66,6 +87,7 @@ class TestSchema < Minitest::Test
|
|
66
87
|
assert_equal "john", hash[:names]
|
67
88
|
end
|
68
89
|
|
90
|
+
|
69
91
|
def test_inherited_schema_should_inherit_extensions
|
70
92
|
hash = {
|
71
93
|
names: "john",
|
@@ -77,6 +99,7 @@ class TestSchema < Minitest::Test
|
|
77
99
|
assert_nil hash[:book]
|
78
100
|
end
|
79
101
|
|
102
|
+
|
80
103
|
def test_complex_schema
|
81
104
|
hash = {
|
82
105
|
name: "john",
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yas
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Albert Tedja
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-11-
|
11
|
+
date: 2015-11-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -66,14 +66,15 @@ files:
|
|
66
66
|
- lib/yas/ext/attribute.rb
|
67
67
|
- lib/yas/ext/migrate.rb
|
68
68
|
- lib/yas/ext/rename.rb
|
69
|
+
- lib/yas/ext/symbolize.rb
|
69
70
|
- lib/yas/ext/whitelist.rb
|
70
71
|
- lib/yas/hash.rb
|
71
|
-
- lib/yas/helper.rb
|
72
72
|
- lib/yas/schema.rb
|
73
73
|
- lib/yas/version.rb
|
74
74
|
- test/ext/test_attribute.rb
|
75
75
|
- test/ext/test_migrate.rb
|
76
76
|
- test/ext/test_rename.rb
|
77
|
+
- test/ext/test_symbolize.rb
|
77
78
|
- test/ext/test_whitelist.rb
|
78
79
|
- test/helper.rb
|
79
80
|
- test/test_schema.rb
|