rov 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|