valligator 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/HISTORY.md +4 -0
- data/README.md +20 -19
- data/VERSION +1 -1
- data/lib/valligator.rb +18 -0
- data/test/lib/valligator/errors_test.rb +1 -1
- data/test/lib/valligator/is_instance_of_test.rb +45 -31
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4c57e3ef079cd6494f2b67e9abe8b5e46336805d
|
4
|
+
data.tar.gz: a6bfdaad97a85777458cc6219b901cea77269b74
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 95a39fb2d9a3b89483587da462de9c593841e2963b8ed4a36ab076182b833ef4f1e360afac7188bbef3b68ebd98a5b837792e699f30c239b6c670962195307f5
|
7
|
+
data.tar.gz: d821f39b08f9974b2fa6ec2793a7d5b53dcadee4aaf936bfb4a32e9c87641af9e8fe44452841947d9361722934e58eaa12d2b06fe5ffc8a9cb197a0e22883e64
|
data/HISTORY.md
ADDED
data/README.md
CHANGED
@@ -40,7 +40,7 @@ There are 3 validations (a.k.a. statements) that the Valligator supports:
|
|
40
40
|
|
41
41
|
The validations passes when testee responds to all (or none in negative case) the methods from the list.
|
42
42
|
|
43
|
-
#### is_instance_of
|
43
|
+
#### is_instance_of, is_a
|
44
44
|
```
|
45
45
|
testee.is_instance_of(*classes)
|
46
46
|
testee.is_not_instance_of(*classes)
|
@@ -49,7 +49,9 @@ The validations passes when testee responds to all (or none in negative case) th
|
|
49
49
|
|
50
50
|
The validations passes when testee is an instance of any class (or not an instance of all the classes in negative case).
|
51
51
|
|
52
|
-
|
52
|
+
**is_instance_of** and **is_not_instance_of** have aliases **is_a** and **is_not_a**
|
53
|
+
|
54
|
+
#### asserts, is, has
|
53
55
|
```
|
54
56
|
testee.asserts(method, *method_args, &block)
|
55
57
|
testee.asserts_not(method, *method_args, &block)
|
@@ -82,38 +84,37 @@ I use _instance_eval_ so that the _value_ could be assessed as _self_, and one w
|
|
82
84
|
Each statement, if it does not fail, returns an instance of the Valligator, so that they can be chained:
|
83
85
|
|
84
86
|
```
|
85
|
-
testee.
|
87
|
+
testee.is_a(String).is_not(:empty?).has(:size){self > 10}.speaks(:to_s)
|
86
88
|
```
|
87
89
|
|
88
90
|
## Errors
|
89
91
|
|
90
92
|
When validation fails a Valligator::ValidationError is raised. The error message contains the full path of the
|
91
|
-
passed validations. If the validation above would fail on
|
93
|
+
passed validations. If the validation above would fail on _is_a_ statement the error message wold look like:
|
92
94
|
|
93
95
|
```
|
94
|
-
Valligator::ValidationError: at testee#1.
|
96
|
+
Valligator::ValidationError: at testee#1.is_a
|
95
97
|
```
|
96
98
|
|
97
|
-
but if it would fail on _has_ then the
|
98
|
-
|
99
|
+
but if it would fail on _has_ then the error would be
|
99
100
|
|
100
101
|
```
|
101
|
-
Valligator::ValidationError: at testee#1.
|
102
|
+
Valligator::ValidationError: at testee#1.is_a.is_not.has
|
102
103
|
```
|
103
104
|
|
104
105
|
You can provide a testee name when you instantiate a Valligator instance, and the name will be used in the error message instead of 'testee#x'
|
105
106
|
|
106
107
|
```
|
107
108
|
testee = Valligator.new('Very long string', 'Short', names: ['long', 'short'])
|
108
|
-
testee.
|
109
|
-
#=> Valligator::ValidationError: at `short.
|
109
|
+
testee.is_a(String).has(:size){self > 10}
|
110
|
+
#=> Valligator::ValidationError: at `short.is_a.has'
|
110
111
|
```
|
111
112
|
|
112
113
|
## Examples
|
113
114
|
|
114
115
|
Validate that testee is an instance of String
|
115
116
|
```
|
116
|
-
Valligator.new('foo').
|
117
|
+
Valligator.new('foo').is_a(String) #=> OK
|
117
118
|
```
|
118
119
|
|
119
120
|
Validate that all testees respond to :to_s and :upcase methods
|
@@ -125,15 +126,15 @@ Valligator.new(*testees).speaks(:to_s, :upcase) #=> OK
|
|
125
126
|
Validate that all testees have size == 3 and start with 'b' and they are Strings
|
126
127
|
```
|
127
128
|
testees = ['boo', 'bar', :baz]
|
128
|
-
Valligator.new(*testees).has(:size){self == 3}.has(:[], 0){self == 'b'}.
|
129
|
-
#=> Valligator::ValidationError: at testee#3.has.has.
|
129
|
+
Valligator.new(*testees).has(:size){self == 3}.has(:[], 0){self == 'b'}.is_a(String)
|
130
|
+
#=> Valligator::ValidationError: at testee#3.has.has.is_a'
|
130
131
|
```
|
131
132
|
|
132
133
|
Validate that all hash values are Integers <= 2
|
133
134
|
```
|
134
135
|
h = { foo: 1, bar: 2, baz: 3 }
|
135
|
-
Valligator.new(*h.values, names: h.keys).
|
136
|
-
#=> Valligator::ValidationError: at `baz.
|
136
|
+
Valligator.new(*h.values, names: h.keys).is_a(Integer).asserts(:<= , 2)
|
137
|
+
#=> Valligator::ValidationError: at `baz.is_a.asserts'
|
137
138
|
```
|
138
139
|
|
139
140
|
## More examples
|
@@ -208,11 +209,11 @@ Using the Valligator we can write all above as:
|
|
208
209
|
require 'valligator'
|
209
210
|
|
210
211
|
def charge!(payee, payment_gateway, order, currency, logger)
|
211
|
-
Valligator.new(user).
|
212
|
+
Valligator.new(user).is_a(User, RemoteSystem).is_not(:blocked?).is(:confirmed?).has(:payment_method).asserts(:can_pay_in?, currency)
|
212
213
|
Valligator.new(payment_gateway).is(:active?).speaks(payee.payment_method)
|
213
214
|
Valligator.new(order).is_not(:deleted?).has(:status) { self == :pending }.does_not_have(:order_items) { empty? }
|
214
215
|
Valligator.new(*order.items).has(:currency){ self == currency }.has(:price) { self > 0 }
|
215
|
-
Valligator.new(logger).
|
216
|
+
Valligator.new(logger).is_a(IO).is_not(:closed?).has(:path) { self != 'dev/null'}
|
216
217
|
Valligator.new(currency).asserts(:==, :usd)
|
217
218
|
|
218
219
|
charge(payee, payment_gateway, order, currency, logger)
|
@@ -227,11 +228,11 @@ require 'valligator'
|
|
227
228
|
include Valligator::Helper
|
228
229
|
|
229
230
|
def charge!(payee, payment_gateway, order, logger, currency)
|
230
|
-
v(user).
|
231
|
+
v(user).is_a(User, RemoteSystem).is_not_blocked?.is_confirmed?.has_payment_method.asserts_can_pay_in?(currency)
|
231
232
|
v(payment_gateway).is_active?.speaks(payee.payment_method)
|
232
233
|
v(order).is_not_deleted?.has_status{ self == :pending }.does_not_have_order_items { empty? }
|
233
234
|
v(*order.items).has_currency{ self == :usd }.has_price { self > 0 }
|
234
|
-
v(logger).
|
235
|
+
v(logger).is_a(IO).is_not_closed?.has_path { self != 'dev/null'}
|
235
236
|
v(currency).asserts(:==, :usd)
|
236
237
|
|
237
238
|
charge(payee, payment_gateway, order, currency, logger)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.2
|
data/lib/valligator.rb
CHANGED
@@ -70,6 +70,8 @@ class Valligator
|
|
70
70
|
# Valligator.new('foo').is_instance_of(Integer, String) #=> OK
|
71
71
|
# Valligator.new('foo').is_instance_of(Integer, Array) #=> Valligator::ValidationError
|
72
72
|
#
|
73
|
+
# @see #is_a
|
74
|
+
#
|
73
75
|
def is_instance_of(*classes)
|
74
76
|
clone._is_instance_of(__method__, *classes)
|
75
77
|
end
|
@@ -85,11 +87,27 @@ class Valligator
|
|
85
87
|
# Valligator.new('foo').is_not_instance_of(Integer, String) #=> Valligator::ValidationError
|
86
88
|
# Valligator.new('foo').is_not_instance_of(Integer, Array) #=> OK
|
87
89
|
#
|
90
|
+
# @see #is_not_a
|
91
|
+
#
|
88
92
|
def is_not_instance_of(*classes)
|
89
93
|
clone._is_instance_of(__method__, *classes)
|
90
94
|
end
|
91
95
|
|
92
96
|
|
97
|
+
# Is an alias for {#is_instance_of} method
|
98
|
+
#
|
99
|
+
def is_a(*classes)
|
100
|
+
clone._is_instance_of(__method__, *classes)
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
# Is an alias for {#is_not_instance_of} method
|
105
|
+
#
|
106
|
+
def is_not_a(*classes)
|
107
|
+
clone._is_instance_of(__method__, *classes)
|
108
|
+
end
|
109
|
+
|
110
|
+
|
93
111
|
# Passes when the testee responds to all the methods
|
94
112
|
#
|
95
113
|
# @param [Array<Symbols>] methods
|
@@ -8,51 +8,65 @@ class TestIsInstanceOf < Minitest::Test
|
|
8
8
|
Valligator::ValidationError
|
9
9
|
end
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
11
|
+
positive_statements = [:is_instance_of, :is_a]
|
12
|
+
negative_statements = [:is_not_instance_of, :is_not_a]
|
13
|
+
all_statements = positive_statements + negative_statements
|
14
|
+
|
15
|
+
all_statements.each do |method|
|
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.%s'" % method
|
18
|
+
err = assert_raises(ArgumentError) { v(:a).send(method) }
|
19
|
+
assert_equal expected, err.message
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
define_method 'test_that__%s__fails_on_wrong_argument_type' % method do
|
24
|
+
expected = "wrong argument type (arg#1 is a Fixnum instead of Class) at `testee#1.%s'" % method
|
25
|
+
err = assert_raises(ArgumentError) { v(:a).send(method, 1) }
|
26
|
+
assert_equal expected, err.message
|
27
|
+
end
|
16
28
|
end
|
17
29
|
|
18
30
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
end
|
31
|
+
positive_statements.each do |method|
|
32
|
+
define_method 'test_that__%s__returns_an_instance_of_valligator' % method do
|
33
|
+
assert_instance_of Valligator, v(:a).send(method, Symbol)
|
34
|
+
end
|
24
35
|
|
25
36
|
|
26
|
-
|
27
|
-
|
28
|
-
|
37
|
+
define_method 'test_that__%s__passes_when_there_is_a_match' % method do
|
38
|
+
v(:a).send(method, Symbol)
|
39
|
+
v(:a).send(method, String, Symbol)
|
40
|
+
v(:a).send(method, Symbol).send(method, Symbol)
|
41
|
+
end
|
29
42
|
|
30
43
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
44
|
+
define_method 'test_that__%s__fails_when_there_is_no_match' % method do
|
45
|
+
assert_raises(error) { v(:a).send(method, String) }
|
46
|
+
assert_raises(error) { v(:a).send(method, String, Integer) }
|
47
|
+
assert_raises(error) { v(:a).send(method, Symbol).send(method, String) }
|
48
|
+
end
|
35
49
|
end
|
36
50
|
|
37
51
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
end
|
52
|
+
negative_statements.each do |method|
|
53
|
+
define_method 'test_that__%s__returns_an_instance_of_valligator' % method do
|
54
|
+
assert_instance_of Valligator, v(:a).send(method, String)
|
55
|
+
end
|
43
56
|
|
44
57
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
58
|
+
define_method 'test_that__%s__passes_when_there_is_no_match' % method do
|
59
|
+
v(:a).send(method, String)
|
60
|
+
v(:a).send(method, String, Integer)
|
61
|
+
v(:a).send(method, String).send(method, NilClass)
|
62
|
+
end
|
50
63
|
|
51
64
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
65
|
+
define_method 'test_that__%s__fails_when_there_is_a_match' % method do
|
66
|
+
assert_raises(error) { v(:a).send(method, Symbol) }
|
67
|
+
assert_raises(error) { v(:a).send(method, String, Symbol) }
|
68
|
+
assert_raises(error) { v(:a).send(method, String).send(method, Symbol) }
|
69
|
+
end
|
56
70
|
end
|
57
71
|
|
58
72
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
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.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Konstantin Dzreev
|
@@ -45,6 +45,7 @@ extensions: []
|
|
45
45
|
extra_rdoc_files: []
|
46
46
|
files:
|
47
47
|
- Gemfile
|
48
|
+
- HISTORY.md
|
48
49
|
- README.md
|
49
50
|
- Rakefile
|
50
51
|
- VERSION
|