valligator 1.0.3 → 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/HISTORY.md +16 -5
- data/README.md +17 -4
- data/VERSION +1 -1
- data/lib/valligator.rb +21 -48
- data/test/lib/valligator/errors_test.rb +10 -0
- data/test/lib/valligator/is_instance_of_test.rb +19 -8
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b3d8ebc145692776bf7f9420a41868941aa287db
|
4
|
+
data.tar.gz: 300432e7de9d78593c799de84373b4921b9225e6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7ecb1005fddd355b81c7730ea47ad75ba9b9342221626ed9c38c075d41f34c344b1fc8f377ebbd8657270a190af72d31faf75c96adceb368a122735d4746b1fb
|
7
|
+
data.tar.gz: f3de17e331ed5aaf1abfb1d3419133c11d22485106352d4d3cb8ea0f9349b8c214581c4e447b4d4bb33a2f0dffb6800a0be967b2d15ab7e8eb68334d7c53c74b
|
data/HISTORY.md
CHANGED
@@ -1,12 +1,23 @@
|
|
1
|
+
#### 1.0.4
|
2
|
+
- Valligator::ValidationError.validation_stack returns the exact position in validation method chain where the validation fails
|
3
|
+
- **is_kind_of** got a new alias **is_an**
|
4
|
+
- **is_not_kind_of** got a new alias **is_not_an**
|
5
|
+
- all alias methods were replaced with ruby's built-in **alias_method**, so error messages will refer to the original method name:
|
6
|
+
Example:
|
7
|
+
123.is_a(String)
|
8
|
+
# old behavior
|
9
|
+
Valligator::ValidationError: wrong number of arguments (0 for 1..Infinity) at `testee#1.is_a
|
10
|
+
# new behavior
|
11
|
+
Valligator::ValidationError: wrong number of arguments (0 for 1..Infinity) at `testee#1.is_kind_of
|
12
|
+
|
1
13
|
#### 1.0.3
|
2
14
|
- **is_instance_of** renamed to **is_kind_of**
|
3
15
|
- **is_not_instance_of** renamed to **is_not_kind_of**
|
4
16
|
- new helper method: Valligator::Helper#vh(Hash)
|
5
17
|
|
6
18
|
#### 1.0.2
|
7
|
-
- **is_instance_of** got alias **is_a**
|
8
|
-
- **is_not_instance_of** got alias **is_not_a**
|
19
|
+
- **is_instance_of** got a new alias **is_a**
|
20
|
+
- **is_not_instance_of** got a new alias **is_not_a**
|
9
21
|
|
10
|
-
#### 1.0.
|
11
|
-
-
|
12
|
-
- **is_not_instance_of** renamed to **is_not_kind_of**
|
22
|
+
#### 1.0.1
|
23
|
+
- couple bug fixes
|
data/README.md
CHANGED
@@ -46,7 +46,7 @@ The validations passes when testee responds to all (or none in negative case) th
|
|
46
46
|
|
47
47
|
|
48
48
|
#### is_kind_of, is_not_kind_of
|
49
|
-
Aliases: **is_a** and **is_not_a**.
|
49
|
+
Aliases: **is_a**, **is_an** and **is_not_a**, **is_not_an**.
|
50
50
|
|
51
51
|
```
|
52
52
|
testee.is_kind_of(*classes)
|
@@ -84,7 +84,7 @@ If it does not sound clear, then it is something like this:
|
|
84
84
|
# is the same as:
|
85
85
|
|
86
86
|
value = :foo.size
|
87
|
-
raise
|
87
|
+
raise if !value.instance_eval { self == 10 }
|
88
88
|
```
|
89
89
|
|
90
90
|
I use _instance_eval_ so that the _value_ could be assessed as _self_, and one would not need to access it using standard block params definition: {|value| value == 10 }.
|
@@ -103,7 +103,7 @@ Each statement, if it does not fail, returns an instance of the Valligator, so t
|
|
103
103
|
When validation fails a Valligator::ValidationError is raised.
|
104
104
|
|
105
105
|
```
|
106
|
-
Valligator.new(:foo).
|
106
|
+
Valligator.new(:foo).is(:empty?) #=>
|
107
107
|
Valligator::ValidationError: `testee#1': method `empty?' returned falsy value
|
108
108
|
```
|
109
109
|
|
@@ -115,6 +115,19 @@ testee.is_a(String).has(:size){self > 10} #=>
|
|
115
115
|
Valligator::ValidationError: `short': method `size' returned falsy value
|
116
116
|
```
|
117
117
|
|
118
|
+
If there was a chain of validations, you can get the exact position of the one that failed:
|
119
|
+
|
120
|
+
```
|
121
|
+
testee = Valligator.new(:foo1)
|
122
|
+
begin
|
123
|
+
# it should die on :boom
|
124
|
+
testee.is_kind_of(Symbol).asserts_not(:empty?).speaks(:boom).has(:to_s){ self == 'foo' }
|
125
|
+
rescue => e
|
126
|
+
puts e.validation_stack #=> "is_kind_of.asserts_not.speaks"
|
127
|
+
end
|
128
|
+
|
129
|
+
```
|
130
|
+
|
118
131
|
## Examples
|
119
132
|
|
120
133
|
Validate that testee is an instance of String
|
@@ -132,7 +145,7 @@ Validate that all testees have size == 3 and start with 'b' and they are Strings
|
|
132
145
|
```
|
133
146
|
testees = ['boo', 'bar', :baz]
|
134
147
|
Valligator.new(*testees).has(:size){self == 3}.has(:[], 0){self == 'b'}.is_a(String) #=>
|
135
|
-
Valligator::ValidationError: `testee#3': should be Symbol
|
148
|
+
Valligator::ValidationError: `testee#3': should not be Symbol
|
136
149
|
```
|
137
150
|
|
138
151
|
Validate that all hash values are Integers <= 2
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.4
|
data/lib/valligator.rb
CHANGED
@@ -2,12 +2,20 @@ require 'pathname'
|
|
2
2
|
require_relative 'valligator_helper'
|
3
3
|
|
4
4
|
class Valligator
|
5
|
-
VERSION
|
5
|
+
VERSION = File.read(Pathname(__FILE__).dirname.join('../VERSION')).strip
|
6
|
+
INFINITY = 1/0.0
|
7
|
+
Error = Class.new(StandardError)
|
6
8
|
|
7
|
-
Error = Class.new(StandardError)
|
8
|
-
ValidationError = Class.new(Error)
|
9
9
|
|
10
|
-
|
10
|
+
class ValidationError < Error
|
11
|
+
attr_reader :validation_stack
|
12
|
+
|
13
|
+
def initialize(message, stack)
|
14
|
+
super(message)
|
15
|
+
@validation_stack = stack.join('.')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
11
19
|
|
12
20
|
attr_reader :testees
|
13
21
|
attr_reader :names
|
@@ -78,7 +86,8 @@ class Valligator
|
|
78
86
|
def is_kind_of(*classes)
|
79
87
|
clone._is_kind_of(__method__, *classes)
|
80
88
|
end
|
81
|
-
|
89
|
+
alias_method :is_a, :is_kind_of
|
90
|
+
alias_method :is_an, :is_kind_of
|
82
91
|
|
83
92
|
# Passes when the testee is not an instance of all of the classes
|
84
93
|
#
|
@@ -95,20 +104,8 @@ class Valligator
|
|
95
104
|
def is_not_kind_of(*classes)
|
96
105
|
clone._is_kind_of(__method__, *classes)
|
97
106
|
end
|
98
|
-
|
99
|
-
|
100
|
-
# Is an alias for {#is_kind_of} method
|
101
|
-
#
|
102
|
-
def is_a(*classes)
|
103
|
-
clone._is_kind_of(__method__, *classes)
|
104
|
-
end
|
105
|
-
|
106
|
-
|
107
|
-
# Is an alias for {#is_not_kind_of} method
|
108
|
-
#
|
109
|
-
def is_not_a(*classes)
|
110
|
-
clone._is_kind_of(__method__, *classes)
|
111
|
-
end
|
107
|
+
alias_method :is_not_a, :is_not_kind_of
|
108
|
+
alias_method :is_not_an, :is_not_kind_of
|
112
109
|
|
113
110
|
|
114
111
|
# Passes when the testee responds to all the methods
|
@@ -168,6 +165,8 @@ class Valligator
|
|
168
165
|
def asserts(method, *args, &block)
|
169
166
|
clone._asserts(__method__, method, *args, &block)
|
170
167
|
end
|
168
|
+
alias_method :is, :asserts
|
169
|
+
alias_method :has, :asserts
|
171
170
|
|
172
171
|
|
173
172
|
# When no block given it passes if the testee, called with a given method and arguments, returns falsy value.
|
@@ -197,34 +196,8 @@ class Valligator
|
|
197
196
|
def asserts_not(method, *args, &block)
|
198
197
|
clone._asserts(__method__, method, *args, &block)
|
199
198
|
end
|
200
|
-
|
201
|
-
|
202
|
-
# Is an alias for {#asserts} method
|
203
|
-
#
|
204
|
-
def is(method, *args, &block)
|
205
|
-
clone._asserts(__method__, method, *args, &block)
|
206
|
-
end
|
207
|
-
|
208
|
-
|
209
|
-
# Is an alias for {#asserts_not} method
|
210
|
-
#
|
211
|
-
def is_not(method, *args, &block)
|
212
|
-
clone._asserts(__method__, method, *args, &block)
|
213
|
-
end
|
214
|
-
|
215
|
-
|
216
|
-
# Is an alias for {#asserts} method
|
217
|
-
#
|
218
|
-
def has(method, *args, &block)
|
219
|
-
clone._asserts(__method__, method, *args, &block)
|
220
|
-
end
|
221
|
-
|
222
|
-
|
223
|
-
# Is an alias for {#asserts_not} method
|
224
|
-
#
|
225
|
-
def does_not_have(method, *args, &block)
|
226
|
-
clone._asserts(__method__, method, *args, &block)
|
227
|
-
end
|
199
|
+
alias_method :is_not, :asserts_not
|
200
|
+
alias_method :does_not_have, :asserts_not
|
228
201
|
|
229
202
|
|
230
203
|
protected
|
@@ -351,7 +324,7 @@ class Valligator
|
|
351
324
|
# @param option [nil,String] msg Error explanation (when required)
|
352
325
|
#
|
353
326
|
def validation_error(idx, msg)
|
354
|
-
raise(
|
327
|
+
raise ValidationError.new("`%s': %s" % [name_by_idx(idx), msg], self.stack)
|
355
328
|
end
|
356
329
|
|
357
330
|
|
@@ -103,4 +103,14 @@ class TestErrors < Minitest::Test
|
|
103
103
|
assert_equal expected, err.message
|
104
104
|
end
|
105
105
|
|
106
|
+
|
107
|
+
#-------------------------------------
|
108
|
+
# #validation_stack
|
109
|
+
#-------------------------------------
|
110
|
+
|
111
|
+
def test__stack_attribute
|
112
|
+
err = assert_raises(error) { v(:foo).is_a(Symbol).is_not_empty?.speaks(:boom).has(:size) { self > 0 } }
|
113
|
+
assert 'is_kind_of.asserts_not.speaks', err.validation_stack
|
114
|
+
end
|
115
|
+
|
106
116
|
end
|
@@ -8,27 +8,25 @@ class TestIsInstanceOf < Minitest::Test
|
|
8
8
|
Valligator::ValidationError
|
9
9
|
end
|
10
10
|
|
11
|
-
positive_statements = [:is_kind_of, :is_a]
|
12
|
-
negative_statements = [:is_not_kind_of, :is_not_a]
|
13
|
-
all_statements = positive_statements + negative_statements
|
11
|
+
positive_statements = [:is_kind_of, :is_a, :is_an]
|
12
|
+
negative_statements = [:is_not_kind_of, :is_not_a, :is_not_an]
|
14
13
|
|
15
|
-
|
14
|
+
|
15
|
+
positive_statements.each do |method|
|
16
16
|
define_method 'test_that__%s__fails_on_wrong_number_of_arguments' % method do
|
17
|
-
expected = "wrong number of arguments (0 for 1..Infinity) at `testee#1
|
17
|
+
expected = "wrong number of arguments (0 for 1..Infinity) at `testee#1.is_kind_of'"
|
18
18
|
err = assert_raises(ArgumentError) { v(:a).send(method) }
|
19
19
|
assert_equal expected, err.message
|
20
20
|
end
|
21
21
|
|
22
22
|
|
23
23
|
define_method 'test_that__%s__fails_on_wrong_argument_type' % method do
|
24
|
-
expected = "wrong argument type (arg#1 is a NilClass instead of Class) at `testee#1
|
24
|
+
expected = "wrong argument type (arg#1 is a NilClass instead of Class) at `testee#1.is_kind_of'"
|
25
25
|
err = assert_raises(ArgumentError) { v(:a).send(method, nil) }
|
26
26
|
assert_equal expected, err.message
|
27
27
|
end
|
28
|
-
end
|
29
28
|
|
30
29
|
|
31
|
-
positive_statements.each do |method|
|
32
30
|
define_method 'test_that__%s__returns_an_instance_of_valligator' % method do
|
33
31
|
assert_instance_of Valligator, v(:a).send(method, Symbol)
|
34
32
|
end
|
@@ -50,6 +48,19 @@ class TestIsInstanceOf < Minitest::Test
|
|
50
48
|
|
51
49
|
|
52
50
|
negative_statements.each do |method|
|
51
|
+
define_method 'test_that__%s__fails_on_wrong_number_of_arguments' % method do
|
52
|
+
expected = "wrong number of arguments (0 for 1..Infinity) at `testee#1.is_not_kind_of'"
|
53
|
+
err = assert_raises(ArgumentError) { v(:a).send(method) }
|
54
|
+
assert_equal expected, err.message
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
define_method 'test_that__%s__fails_on_wrong_argument_type' % method do
|
59
|
+
expected = "wrong argument type (arg#1 is a NilClass instead of Class) at `testee#1.is_not_kind_of'"
|
60
|
+
err = assert_raises(ArgumentError) { v(:a).send(method, nil) }
|
61
|
+
assert_equal expected, err.message
|
62
|
+
end
|
63
|
+
|
53
64
|
define_method 'test_that__%s__returns_an_instance_of_valligator' % method do
|
54
65
|
assert_instance_of Valligator, v(:a).send(method, String)
|
55
66
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: valligator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Konstantin Dzreev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-10-
|
11
|
+
date: 2017-10-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|