rov 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.
- checksums.yaml +7 -0
- data/README.md +217 -0
- data/lib/rov.rb +10 -0
- data/lib/rov/common.rb +54 -0
- data/lib/rov/do_validate.rb +89 -0
- data/lib/rov/raise_error.rb +30 -0
- data/lib/rov/template.rb +313 -0
- data/lib/rov/validate.rb +30 -0
- data/lib/rov/version.rb +3 -0
- metadata +61 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA512:
|
3
|
+
data.tar.gz: 5c17f73e68aca3537540c8ab0c7d75beebeff0150041b96c2e8a70741614d30d22fde5135ea86a0ff4b005f674074c72d40443090560538170db29c951d83f80
|
4
|
+
metadata.gz: 8285b132b2ed8e9f35ca24d9a919889ab94bf288f54834bd83642e5a266cddf4ff42d1dadf6139943d2a35edd8b8c4bfc12ed44fe1bafcfcf6b0f9cc9a4c1021
|
5
|
+
SHA1:
|
6
|
+
data.tar.gz: 909b6429fbdc9baf33b949866a8008a425fa6a7e
|
7
|
+
metadata.gz: 7ad2c1c95ab319ac10e0e85c5f779bcc89b2adf9
|
data/README.md
ADDED
@@ -0,0 +1,217 @@
|
|
1
|
+
Robject-Validator
|
2
|
+
=================
|
3
|
+
|
4
|
+
## Description
|
5
|
+
Robject-Validator(Rov) is a object validator for Ruby. Usually there are many
|
6
|
+
different data objetcts in your system, and you have to ensure the
|
7
|
+
accuracy of the data objects. It's terrible to write validation code for
|
8
|
+
each object. It will confuse your system and has high risk for bug.
|
9
|
+
|
10
|
+
Rov provides a general mechanism to validate all data objects. All you need is
|
11
|
+
defining template for each object, and then Rov will validate them.
|
12
|
+
|
13
|
+
|
14
|
+
## Requires
|
15
|
+
Rov has no dependencies, unless your objects need other gem packages.
|
16
|
+
|
17
|
+
However, your Ruby version can not be less than 1.8.7.
|
18
|
+
|
19
|
+
## Install
|
20
|
+
From rubygems.org:
|
21
|
+
|
22
|
+
$ gem install rov
|
23
|
+
|
24
|
+
Or install Rov from the git repo:
|
25
|
+
|
26
|
+
$ gem build rov.gemspec
|
27
|
+
$ gem install rov-{version}.gem
|
28
|
+
|
29
|
+
## Basic usage
|
30
|
+
First all, you need to define a template for object. The template is a class
|
31
|
+
inherited from `Rov::Template`, and your object is defined in the instance variable
|
32
|
+
`@template` of the template class.
|
33
|
+
|
34
|
+
For example, a hash object that contains several properties, name, sex, age, email:
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
class Person < Rov::Template
|
38
|
+
@template = {
|
39
|
+
:name => kind_of(String),
|
40
|
+
:age => kind_of(Fixnum),
|
41
|
+
:sex => any_of([:male, :female]),
|
42
|
+
:email => kind_of(String),
|
43
|
+
}
|
44
|
+
end
|
45
|
+
```
|
46
|
+
|
47
|
+
`kind_of` and `any_of` are class methods of Rov::Template.
|
48
|
+
|
49
|
+
`kind_of()` takes one argument which is a class. It means the data must be a object
|
50
|
+
of String(or its child class).
|
51
|
+
|
52
|
+
`any_of()` aslo takes one argument which is an array. It means the data must be a
|
53
|
+
element of the array. The element of the array can be any type, symbol, string,
|
54
|
+
class, or event a template class(yes, templates can be nested with each other).
|
55
|
+
|
56
|
+
After defined, Rov could validate the specific data. Suppose the specific data
|
57
|
+
`data`:
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
data = {
|
61
|
+
:name => "Scarlet",
|
62
|
+
:age => 30,
|
63
|
+
:sex => :female,
|
64
|
+
:email => "scarlet@email.com",
|
65
|
+
}
|
66
|
+
validator = Rov::Validate.new(Person)
|
67
|
+
status, error_msg = validator.do_validate(data)
|
68
|
+
end
|
69
|
+
```
|
70
|
+
|
71
|
+
`do_validate` method return two value: the first is the result if validated or not, and
|
72
|
+
the second one is error massage if validation fails.
|
73
|
+
|
74
|
+
## Advanced Usage
|
75
|
+
|
76
|
+
### Required Keys
|
77
|
+
If your hash object must contain several specified keys, you can use instance variable
|
78
|
+
`@required`. `@required` must be given an array, element in which must present in
|
79
|
+
specific data, or validation will fail. By default, `@required` is an empty array. that
|
80
|
+
is, the specific data can an empty hash.
|
81
|
+
|
82
|
+
For Example:
|
83
|
+
|
84
|
+
```ruby
|
85
|
+
class Person < Rov::Template
|
86
|
+
@template = {
|
87
|
+
:name => kind_of(String),
|
88
|
+
:age => kind_of(Fixnum),
|
89
|
+
:sex => any_of([:male, :female]),
|
90
|
+
:email => kind_of(String),
|
91
|
+
}
|
92
|
+
@required = [:name, :age]
|
93
|
+
end
|
94
|
+
```
|
95
|
+
|
96
|
+
As definition, the specific `Person` data must contain `:name` and `:age`.
|
97
|
+
|
98
|
+
|
99
|
+
### Ordered Array
|
100
|
+
If the template is given an array, then the specific data must be included in the array.
|
101
|
+
By default, there is no restriction on the order of the elements. But you can want to
|
102
|
+
do it, there is a instance variable `@ordered`. If `@ordered` will be set `true`, Rov
|
103
|
+
will validate the specific array with the order which defined in template.
|
104
|
+
|
105
|
+
|
106
|
+
### List of Template Methods
|
107
|
+
There are five available template methods:
|
108
|
+
|
109
|
+
+ `any_of()`
|
110
|
+
|
111
|
+
As you known, `any_of()` means the specific data should be included in the given
|
112
|
+
array. `any_of()` can be used anywhere, such as hash's key:
|
113
|
+
|
114
|
+
```ruby
|
115
|
+
class People < Rov::Template
|
116
|
+
@template = {
|
117
|
+
any_of(names) => Person,
|
118
|
+
}
|
119
|
+
end
|
120
|
+
```
|
121
|
+
|
122
|
+
Suppose the argument of `any_of()` `names` is an array which contains many names.
|
123
|
+
|
124
|
+
Besides, this example shows how to nested template in other template.
|
125
|
+
|
126
|
+
+ `kind_of()`
|
127
|
+
|
128
|
+
+ `instance_of()`
|
129
|
+
|
130
|
+
The difference with `kind_of()` is that `instance_of()` can not be an instance of
|
131
|
+
the class's child class.
|
132
|
+
|
133
|
+
+ `in_range()`
|
134
|
+
|
135
|
+
This method takes an object of `Range`, and the specific data should be included
|
136
|
+
in it.
|
137
|
+
|
138
|
+
+ `anything()`
|
139
|
+
|
140
|
+
This function does not accept any arguments. Any specific data will be validated
|
141
|
+
if the template data is defined with `anything()`.
|
142
|
+
|
143
|
+
|
144
|
+
### Custom Template Method
|
145
|
+
You can define new template method. Template method should return a class inherited
|
146
|
+
from Rov::Template, like defining template class. In the class, two things must be
|
147
|
+
presented, `@template` and `validate_method()`.
|
148
|
+
|
149
|
+
`@template` is same as `@template` in the template class. And `validate_method()`
|
150
|
+
returns a method by which Rov validates the specific data.
|
151
|
+
|
152
|
+
For example, it defines a method `email()` to validate specific data must be a
|
153
|
+
email address.
|
154
|
+
|
155
|
+
```ruby
|
156
|
+
def email()
|
157
|
+
email_cls = Class.new(Rov::Template) do
|
158
|
+
# @template =
|
159
|
+
def validate_method
|
160
|
+
m = lambda do |actual_value|
|
161
|
+
if actual_value.is_a?(String) and
|
162
|
+
(actual_value =~ /^[a-zA-Z0-9_.+\-]+@[a-zA-Z0-9\-]+\.[a-zA-Z0-9\-.]+$/) == 0
|
163
|
+
[true, ""]
|
164
|
+
else
|
165
|
+
raise_validation_error(:invalid_email)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
return m
|
169
|
+
end
|
170
|
+
end
|
171
|
+
return email_cls
|
172
|
+
end
|
173
|
+
```
|
174
|
+
|
175
|
+
Because the format of email address is unchanged, the template should be a constant(
|
176
|
+
the regex), so there is only `validate_method()` in `email()`. The method that returned
|
177
|
+
by `validate_method()` return two value(status and an empty string) if validation succeed.
|
178
|
+
If validation fails, just call `raise_validation_error()` with a symbol.
|
179
|
+
|
180
|
+
|
181
|
+
### Custom Validation Method
|
182
|
+
Sometimes, you may have some special requirements. Rov provides you a way to define
|
183
|
+
your custom validation method.
|
184
|
+
|
185
|
+
```ruby
|
186
|
+
class Person < Rov::Template
|
187
|
+
@template = {
|
188
|
+
# ...
|
189
|
+
:email => kind_of(String),
|
190
|
+
:address => kind_of(String),
|
191
|
+
:zip_code => kind_of(Fixnum),
|
192
|
+
}
|
193
|
+
|
194
|
+
def validate(actual_value)
|
195
|
+
r = [actual_value[:address], actual_value[:zip_code]]
|
196
|
+
return ((not r.any?) or r.all?)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
```
|
200
|
+
|
201
|
+
You can define `Rov::Template#validate` method to implement your custom method.
|
202
|
+
|
203
|
+
`Rov::Template#validate()` takes one argument `actual_value` which is specific
|
204
|
+
data. The example above means the keys `:address` and `:zip_code` are either both
|
205
|
+
presented, or both not.
|
206
|
+
|
207
|
+
|
208
|
+
### Simple Way Defining Template
|
209
|
+
Rov provides a simple way to define a templete, if the template is not complicated.
|
210
|
+
With `Rov::Template.create_template()`, you don't need to define a class for each
|
211
|
+
template.
|
212
|
+
|
213
|
+
```ruby
|
214
|
+
person_cls = Rov::Template.create_template({:name => kind_of(String), :age => kind_of(Fixnum)})
|
215
|
+
validator = Rov::Validate.new(person_cls)
|
216
|
+
validator.do_validate(specific_data)
|
217
|
+
```
|
data/lib/rov.rb
ADDED
data/lib/rov/common.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# -*- coding : utf-8 -*-
|
2
|
+
|
3
|
+
module Rov
|
4
|
+
module Common
|
5
|
+
def self.template_cls?(template)
|
6
|
+
return (template.class == Class and template.superclass == Template)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.string_hash_key(hash)
|
10
|
+
r = hash.map do |k, v|
|
11
|
+
if k.is_a?(Symbol)
|
12
|
+
[k.to_s, v]
|
13
|
+
else
|
14
|
+
[k, v]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
return Hash[r]
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.string_array_element(array)
|
21
|
+
r = array.map do |e|
|
22
|
+
if e.is_a?(Symbol)
|
23
|
+
e.to_s
|
24
|
+
else
|
25
|
+
e
|
26
|
+
end
|
27
|
+
end
|
28
|
+
return r
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.with_symbol_access(hash)
|
32
|
+
return HashWithSymbolAccess[hash.entries]
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class HashWithSymbolAccess < Hash
|
39
|
+
def [](key)
|
40
|
+
if self.keys.include?(key)
|
41
|
+
return super(key)
|
42
|
+
elsif key.is_a?(Symbol) and self.keys.include?(key.to_s)
|
43
|
+
return super(key.to_s)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def []=(key, value)
|
48
|
+
if self.keys.include?(key)
|
49
|
+
super(key, value)
|
50
|
+
elsif key.is_a?(Symbol) and self.keys.include?(key.to_s)
|
51
|
+
super(key.to_s, value)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# -*- coding : utf-8 -*-
|
2
|
+
module Rov
|
3
|
+
class DoValidate
|
4
|
+
|
5
|
+
include RaiseError
|
6
|
+
|
7
|
+
def initialize(template)
|
8
|
+
if Common.template_cls?(template)
|
9
|
+
@template_obj = template.new(self)
|
10
|
+
else
|
11
|
+
@template_obj = Template.new(self)
|
12
|
+
@template_obj.set_template_value(template)
|
13
|
+
end
|
14
|
+
|
15
|
+
@template_value = @template_obj.get_template_value_for_validation
|
16
|
+
@validate_method = @template_obj.validate_method
|
17
|
+
|
18
|
+
if @template_value.class == self.class.superclass
|
19
|
+
clone_self(@template_value)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def clone_self(template_obj)
|
24
|
+
@template_value = template_obj.get_template_value
|
25
|
+
@validate_method = template_obj.get_validate_method
|
26
|
+
@template_obj = template_obj.get_template_obj
|
27
|
+
end
|
28
|
+
|
29
|
+
def get_template_value
|
30
|
+
return @template_value
|
31
|
+
end
|
32
|
+
|
33
|
+
def get_validate_method
|
34
|
+
return @validate_method
|
35
|
+
end
|
36
|
+
|
37
|
+
def get_template_obj
|
38
|
+
return @template_obj
|
39
|
+
end
|
40
|
+
|
41
|
+
def validate(actual_value)
|
42
|
+
set_value_hash({
|
43
|
+
:actual_value => actual_value,
|
44
|
+
:template_value => @template_obj.get_template_value,
|
45
|
+
:template_value_cls => @template_obj.class,
|
46
|
+
})
|
47
|
+
status, msg = @validate_method[actual_value]
|
48
|
+
if not status
|
49
|
+
raise RaiseError::InvalidConfig, msg
|
50
|
+
else
|
51
|
+
if not custom_validate(actual_value)
|
52
|
+
raise_validation_error(:self_validate_fail)
|
53
|
+
end
|
54
|
+
return true, ""
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def do_validate(actual_value)
|
59
|
+
begin
|
60
|
+
status, msg = validate(actual_value)
|
61
|
+
rescue RaiseError::InvalidConfig => ex
|
62
|
+
status = false
|
63
|
+
|
64
|
+
# it can `raise` a array when ruby version less 1.9.3. # or the array will be inspected.
|
65
|
+
# so, pass the message to eval() when it is a string.
|
66
|
+
if ex.message.is_a?(String)
|
67
|
+
msg = eval(ex.message)
|
68
|
+
else
|
69
|
+
msg = ex.message
|
70
|
+
end
|
71
|
+
end
|
72
|
+
return status, msg
|
73
|
+
end
|
74
|
+
|
75
|
+
def custom_validate(actual_value)
|
76
|
+
return get_template_obj.do_custom_validate(actual_value)
|
77
|
+
end
|
78
|
+
|
79
|
+
def get_option
|
80
|
+
return {}
|
81
|
+
end
|
82
|
+
|
83
|
+
def set_value_hash(hash={})
|
84
|
+
@value_hash ||= {}
|
85
|
+
@value_hash.merge!(hash)
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- coding : utf-8 -*-
|
2
|
+
module Rov
|
3
|
+
module RaiseError
|
4
|
+
class InvalidConfig < StandardError
|
5
|
+
end
|
6
|
+
|
7
|
+
def raise_validation_error(error_type)
|
8
|
+
raise InvalidConfig, [error_type, get_error_str(error_type)]
|
9
|
+
end
|
10
|
+
|
11
|
+
def get_error_str(error_type)
|
12
|
+
template_value = @value_hash[:template_value]
|
13
|
+
actual_value = @value_hash[:actual_value]
|
14
|
+
|
15
|
+
types = {
|
16
|
+
:not_include => "#{actual_value.inspect} not in `#{template_value.inspect}`",
|
17
|
+
:type_error => "type of `#{actual_value.inspect}`(#{actual_value.class}) should be #{template_value.class}",
|
18
|
+
:invalid_key => "invalid key `#{@value_hash[:actual_hash_key].inspect}` in `#{actual_value.inspect}`",
|
19
|
+
:surplus_element => "surplus element `#{@value_hash[:actual_array_element].inspect}` in `#{actual_value.inspect}`",
|
20
|
+
:invalid_element => "invalid element in `#{actual_value.inspect}`",
|
21
|
+
:not_in_range => "`#{actual_value.inspect}` not in range of `#{template_value}`",
|
22
|
+
:not_eq => "`#{actual_value.inspect}` not equal to `#{template_value}`",
|
23
|
+
:not_required => "no required key: `#{@value_hash[:required_key].inspect}` in `#{actual_value.inspect}`",
|
24
|
+
:self_validate_fail => "`#{@value_hash[:template_value_cls].inspect}` custom validate method failed",
|
25
|
+
}
|
26
|
+
return types[error_type] || "#{error_type}: #{actual_value.inspect}"
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
data/lib/rov/template.rb
ADDED
@@ -0,0 +1,313 @@
|
|
1
|
+
# -*- coding : utf-8 -*-
|
2
|
+
module Rov
|
3
|
+
class Template
|
4
|
+
@required = []
|
5
|
+
@ordered = false
|
6
|
+
|
7
|
+
def self.create_template(template_value)
|
8
|
+
template_cls = Class.new(self) do
|
9
|
+
@template = template_value
|
10
|
+
end
|
11
|
+
return template_cls
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.template
|
15
|
+
return @template
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.template=(value)
|
19
|
+
@template = value
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.required
|
23
|
+
return @required.to_a
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.ordered?
|
27
|
+
return @ordered
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize(validate_obj)
|
31
|
+
@validate_obj = validate_obj
|
32
|
+
@raw_template_value = self.class.template
|
33
|
+
@required = self.class.required
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_validate_option
|
37
|
+
return @validate_obj.get_option()
|
38
|
+
end
|
39
|
+
|
40
|
+
def set_template_value(value)
|
41
|
+
@raw_template_value = value
|
42
|
+
end
|
43
|
+
|
44
|
+
def get_template_value
|
45
|
+
if @template_value
|
46
|
+
return @template_value
|
47
|
+
end
|
48
|
+
value = @raw_template_value
|
49
|
+
validate_option = get_validate_option()
|
50
|
+
|
51
|
+
if validate_option[:json]
|
52
|
+
if value.is_a?(Hash)
|
53
|
+
value = Common.string_hash_key(value)
|
54
|
+
value = Common.with_symbol_access(value)
|
55
|
+
elsif value.is_a?(Array)
|
56
|
+
value = Common.string_array_element(value)
|
57
|
+
elsif value.is_a?(Symbol)
|
58
|
+
value = value.to_s
|
59
|
+
elsif value == Symbol
|
60
|
+
value = String
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
@template_value = value
|
65
|
+
return @template_value
|
66
|
+
end
|
67
|
+
|
68
|
+
def get_template_value_for_validation
|
69
|
+
if @template_value_for_validation
|
70
|
+
return @template_value_for_validation
|
71
|
+
end
|
72
|
+
value = get_template_value()
|
73
|
+
case
|
74
|
+
when value.is_a?(Hash)
|
75
|
+
value = Hash[
|
76
|
+
value.map do |k, v|
|
77
|
+
if Common.template_cls?(k)
|
78
|
+
k = @validate_obj.class.new(k)
|
79
|
+
end
|
80
|
+
[k, @validate_obj.class.new(v)]
|
81
|
+
end
|
82
|
+
]
|
83
|
+
when value.is_a?(Array)
|
84
|
+
value = value.map {|a| @validate_obj.class.new(a)}
|
85
|
+
# else
|
86
|
+
# if value.class == @validate_obj.class.superclass
|
87
|
+
# # clone_self(value)
|
88
|
+
# value = value
|
89
|
+
# else
|
90
|
+
# # @template_value = value
|
91
|
+
# value = value
|
92
|
+
# end
|
93
|
+
end
|
94
|
+
@template_value_for_validation = value
|
95
|
+
return @template_value_for_validation
|
96
|
+
end
|
97
|
+
|
98
|
+
def validate_method
|
99
|
+
value = get_template_value_for_validation
|
100
|
+
case
|
101
|
+
when value.is_a?(Hash)
|
102
|
+
m = method(:validate_hash)
|
103
|
+
when value.is_a?(Array)
|
104
|
+
m = method(:validate_array)
|
105
|
+
else
|
106
|
+
if value.is_a?(Class) and value.superclass == self.class.superclass
|
107
|
+
m = value.new(@validate_obj).validate_method
|
108
|
+
else
|
109
|
+
m = method(:validate_other)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
return m
|
114
|
+
end
|
115
|
+
|
116
|
+
def validate_required(array)
|
117
|
+
self.required.each do |key|
|
118
|
+
if not @validate_obj.class.new(array).do_validate([key])[0]
|
119
|
+
@validate_obj.set_value_hash(:required_key => key)
|
120
|
+
@validate_obj.raise_validation_error(:not_required)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def validate_hash(actual_hash)
|
126
|
+
_template_value = get_template_value_for_validation
|
127
|
+
if actual_hash.class != _template_value.class
|
128
|
+
@validate_obj.raise_validation_error(:type_error)
|
129
|
+
end
|
130
|
+
actual_hash.each_pair do |k, v|
|
131
|
+
@validate_obj.set_value_hash(:actual_hash_key => k)
|
132
|
+
if _template_value.keys.include?(k)
|
133
|
+
_template_value[k].validate(v)
|
134
|
+
else
|
135
|
+
is_exist = false
|
136
|
+
(_template_value.keys.find_all {|p| p.class == @validate_obj.class.superclass or p.class == @validate_obj.class}).each do |d|
|
137
|
+
if d.do_validate(k)[0]
|
138
|
+
_template_value[d].validate(v)
|
139
|
+
is_exist = true
|
140
|
+
end
|
141
|
+
end
|
142
|
+
if not is_exist
|
143
|
+
@validate_obj.raise_validation_error(:invalid_key)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
self.validate_required(actual_hash.keys)
|
149
|
+
|
150
|
+
return [true, ""]
|
151
|
+
end
|
152
|
+
|
153
|
+
def validate_array(actual_array)
|
154
|
+
_template_value = get_template_value_for_validation
|
155
|
+
if actual_array.class != _template_value.class
|
156
|
+
@validate_obj.raise_validation_error(:type_error)
|
157
|
+
end
|
158
|
+
|
159
|
+
if self.ordered?
|
160
|
+
actual_array.zip(_template_value).each do |real_element, template_element|
|
161
|
+
if template_element.nil?
|
162
|
+
@validate_obj.set_value_hash(:actual_array_element => real_element)
|
163
|
+
@validate_obj.raise_validation_error(:surplus_element)
|
164
|
+
end
|
165
|
+
template_element.validate(real_element)
|
166
|
+
end
|
167
|
+
else
|
168
|
+
actual_array.each do |re|
|
169
|
+
if _template_value.map {|te| te.do_validate(re)[0]}.none?
|
170
|
+
@validate_obj.raise_validation_error(:invalid_element)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
self.validate_required(actual_array)
|
174
|
+
end
|
175
|
+
|
176
|
+
return [true, ""]
|
177
|
+
end
|
178
|
+
|
179
|
+
def validate_other(actual_value)
|
180
|
+
_template_value = get_template_value_for_validation
|
181
|
+
if not _template_value == actual_value
|
182
|
+
@validate_obj.raise_validation_error(:not_eq)
|
183
|
+
end
|
184
|
+
return [true, ""]
|
185
|
+
end
|
186
|
+
|
187
|
+
def required
|
188
|
+
_required = @required
|
189
|
+
if get_validate_option[:json]
|
190
|
+
case
|
191
|
+
when _required.is_a?(Hash)
|
192
|
+
_required = Common.string_hash_key(_required)
|
193
|
+
when _required.is_a?(Array)
|
194
|
+
_required = Common.string_array_element(_required)
|
195
|
+
when _required.is_a?(Symbol)
|
196
|
+
_required = _required.to_s
|
197
|
+
end
|
198
|
+
end
|
199
|
+
return _required
|
200
|
+
end
|
201
|
+
|
202
|
+
def ordered?
|
203
|
+
return self.class.ordered?
|
204
|
+
end
|
205
|
+
|
206
|
+
def do_custom_validate(actual_value)
|
207
|
+
if get_validate_option[:json]
|
208
|
+
case
|
209
|
+
when actual_value.is_a?(Hash)
|
210
|
+
actual_value = Common.with_symbol_access(actual_value)
|
211
|
+
when actual_value.is_a?(Array)
|
212
|
+
actual_value = Common.string_array_element(actual_value)
|
213
|
+
when actual_value.is_a?(Symbol)
|
214
|
+
actual_value = actual_value.to_s
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
return self.validate(actual_value)
|
219
|
+
end
|
220
|
+
|
221
|
+
def validate(actual_value)
|
222
|
+
return true
|
223
|
+
end
|
224
|
+
|
225
|
+
def raise_validation_error(error_type)
|
226
|
+
return @validate_obj.raise_validation_error(error_type)
|
227
|
+
end
|
228
|
+
|
229
|
+
# ---------------------------------------------------
|
230
|
+
def self.any_of(lst)
|
231
|
+
any_of_cls = Class.new(Rov::Template) do
|
232
|
+
@template = AnyOfArray.new(lst)
|
233
|
+
def validate_method
|
234
|
+
m = lambda do |actual_value|
|
235
|
+
is_exist = false
|
236
|
+
self.get_template_value_for_validation.each do |_template_value|
|
237
|
+
if _template_value.do_validate(actual_value)[0]
|
238
|
+
is_exist = true
|
239
|
+
break
|
240
|
+
end
|
241
|
+
end
|
242
|
+
if not is_exist
|
243
|
+
@validate_obj.raise_validation_error(:not_include)
|
244
|
+
end
|
245
|
+
[true, ""]
|
246
|
+
end
|
247
|
+
return m
|
248
|
+
end
|
249
|
+
end
|
250
|
+
return any_of_cls
|
251
|
+
end
|
252
|
+
|
253
|
+
def self.instance_of(cls)
|
254
|
+
instance_of_cls = Class.new(Rov::Template) do
|
255
|
+
@template = cls
|
256
|
+
|
257
|
+
def validate_method
|
258
|
+
m = lambda do |actual_value|
|
259
|
+
if not actual_value.instance_of?(self.get_template_value)
|
260
|
+
@validate_obj.raise_validation_error(:type_error)
|
261
|
+
end
|
262
|
+
[true, ""]
|
263
|
+
end
|
264
|
+
return m
|
265
|
+
end
|
266
|
+
end
|
267
|
+
return instance_of_cls
|
268
|
+
end
|
269
|
+
|
270
|
+
def self.kind_of(cls)
|
271
|
+
kind_of_cls = Class.new(Rov::Template) do
|
272
|
+
@template = cls
|
273
|
+
|
274
|
+
def validate_method
|
275
|
+
m = lambda do |actual_value|
|
276
|
+
if not actual_value.is_a?(self.get_template_value)
|
277
|
+
@validate_obj.raise_validation_error(:type_error)
|
278
|
+
end
|
279
|
+
[true, ""]
|
280
|
+
end
|
281
|
+
return m
|
282
|
+
end
|
283
|
+
end
|
284
|
+
return kind_of_cls
|
285
|
+
end
|
286
|
+
|
287
|
+
def self.in_range(_range)
|
288
|
+
in_range_cls = Class.new(Rov::Template) do
|
289
|
+
@template = _range
|
290
|
+
|
291
|
+
def validate_method
|
292
|
+
m = lambda do |actual_value|
|
293
|
+
if not self.get_template_value.include?(actual_value)
|
294
|
+
@validate_obj.raise_validation_error(:not_in_range)
|
295
|
+
end
|
296
|
+
[true, ""]
|
297
|
+
end
|
298
|
+
return m
|
299
|
+
end
|
300
|
+
end
|
301
|
+
return in_range_cls
|
302
|
+
end
|
303
|
+
|
304
|
+
def self.anything
|
305
|
+
return kind_of(Object)
|
306
|
+
end
|
307
|
+
|
308
|
+
# ---------------------------------------------------
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
class AnyOfArray < Array
|
313
|
+
end
|
data/lib/rov/validate.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- coding : utf-8 -*-
|
2
|
+
module Rov
|
3
|
+
class Validate
|
4
|
+
def self.validate(template, actual_value, option={})
|
5
|
+
v = self.new(template)
|
6
|
+
return v.do_validate(actual_value, option)
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(template)
|
10
|
+
@template = template
|
11
|
+
end
|
12
|
+
|
13
|
+
def do_validate(actual_value, option={})
|
14
|
+
validate_cls = Class.new(DoValidate) do
|
15
|
+
@option = option
|
16
|
+
|
17
|
+
def self.get_option
|
18
|
+
return @option
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_option
|
22
|
+
return self.class.get_option
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
validate_obj = validate_cls.new(@template)
|
27
|
+
validate_obj.do_validate(actual_value)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/rov/version.rb
ADDED
metadata
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rov
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Handsome Cheung
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2014-11-01 00:00:00 Z
|
13
|
+
dependencies: []
|
14
|
+
|
15
|
+
description: rov provides a general mechanism to validate all objects. All you need is defining template for each object, and then rov will validate them.
|
16
|
+
email:
|
17
|
+
- handsomecheung@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- README.md
|
26
|
+
- lib/rov.rb
|
27
|
+
- lib/rov/common.rb
|
28
|
+
- lib/rov/do_validate.rb
|
29
|
+
- lib/rov/raise_error.rb
|
30
|
+
- lib/rov/template.rb
|
31
|
+
- lib/rov/validate.rb
|
32
|
+
- lib/rov/version.rb
|
33
|
+
homepage: https://github.com/handsomecheung/Robject-Validator
|
34
|
+
licenses:
|
35
|
+
- GPL-3.0
|
36
|
+
metadata: {}
|
37
|
+
|
38
|
+
post_install_message:
|
39
|
+
rdoc_options: []
|
40
|
+
|
41
|
+
require_paths:
|
42
|
+
- lib
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.8.7
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: "0"
|
53
|
+
requirements: []
|
54
|
+
|
55
|
+
rubyforge_project:
|
56
|
+
rubygems_version: 2.4.2
|
57
|
+
signing_key:
|
58
|
+
specification_version: 4
|
59
|
+
summary: rov(Robject Validator) is a object validator for Ruby
|
60
|
+
test_files: []
|
61
|
+
|