valligator 1.0.3 → 1.0.4
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 +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
|