attestor 1.0.0 → 2.0.0
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/.travis.yml +1 -2
- data/README.md +69 -55
- data/config/metrics/rubocop.yml +4 -0
- data/lib/attestor/invalid_error.rb +1 -12
- data/lib/attestor/policy/and.rb +2 -19
- data/lib/attestor/policy/negator.rb +2 -29
- data/lib/attestor/policy/node.rb +7 -33
- data/lib/attestor/policy/not.rb +2 -27
- data/lib/attestor/policy/or.rb +2 -19
- data/lib/attestor/policy/xor.rb +2 -19
- data/lib/attestor/policy.rb +0 -18
- data/lib/attestor/report.rb +51 -0
- data/lib/attestor/validations/delegator.rb +3 -18
- data/lib/attestor/validations/message.rb +1 -16
- data/lib/attestor/validations/reporter.rb +21 -0
- data/lib/attestor/validations/validator.rb +4 -63
- data/lib/attestor/validations/validators.rb +13 -41
- data/lib/attestor/validations.rb +12 -1
- data/lib/attestor/version.rb +1 -1
- data/lib/attestor.rb +2 -0
- data/spec/features/example_spec.rb +5 -5
- data/spec/support/policies.rb +5 -5
- data/spec/tests/policy/and_spec.rb +2 -2
- data/spec/tests/policy/node_spec.rb +9 -9
- data/spec/tests/policy/not_spec.rb +2 -2
- data/spec/tests/policy/or_spec.rb +2 -2
- data/spec/tests/policy/xor_spec.rb +2 -2
- data/spec/tests/policy_spec.rb +0 -48
- data/spec/tests/report_spec.rb +106 -0
- data/spec/tests/validations/delegator_spec.rb +6 -6
- data/spec/tests/validations/message_spec.rb +1 -1
- data/spec/tests/validations/reporter_spec.rb +47 -0
- data/spec/tests/validations/validator_spec.rb +56 -74
- data/spec/tests/validations/validators_spec.rb +81 -4
- data/spec/tests/validations_spec.rb +98 -10
- metadata +9 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1b4d9f6dfa1931f69062623223fafaf32ec4d158
|
4
|
+
data.tar.gz: a18709a18446af9c58a71287eb9b3d923c125aed
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fadf072439c8efa450e86ff37f7dd5778c67ce7a087eaea4e012e0267d9dce2b877283b76c04b1434b1ab0d17b7a00a48317ddeee766304d7ff08ebb02c66109
|
7
|
+
data.tar.gz: 0c5fccf30fe0cfc574d71b3235da77acc904c3f537f4d9ffb4887184925d42c57d82736f99d0af0954fe000c0bc141cc1793bd15911275485bfcfc648bb235c6
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -37,7 +37,12 @@ To solve the problem, the `attestor` gem:
|
|
37
37
|
Approach
|
38
38
|
--------
|
39
39
|
|
40
|
-
Instead of collecting errors inside the object, the module
|
40
|
+
Instead of collecting errors inside the object, the module defines two instance methods:
|
41
|
+
|
42
|
+
* `validate!` raises an exception (`Attestor::InvalidError`), that carries errors outside of the object.
|
43
|
+
* `validate` - the safe version of `validate!`. It rescues an exception and returns special result object, that carries error info outside of the object.
|
44
|
+
|
45
|
+
The object stays untouched (and can be made immutable).
|
41
46
|
|
42
47
|
Installation
|
43
48
|
------------
|
@@ -67,18 +72,10 @@ Basic Use
|
|
67
72
|
Declare validation in the same way as ActiveModel's `.validate` method does:
|
68
73
|
|
69
74
|
```ruby
|
70
|
-
|
75
|
+
Transfer = Struct.new(:debet, :credit) do
|
71
76
|
include Attestor::Validations
|
72
77
|
|
73
78
|
validate :consistent
|
74
|
-
end
|
75
|
-
```
|
76
|
-
|
77
|
-
You have to define an instance validator method (that can be private):
|
78
|
-
|
79
|
-
```ruby
|
80
|
-
class Transfer < Struct.new(:debet, :credit)
|
81
|
-
# ...
|
82
79
|
|
83
80
|
private
|
84
81
|
|
@@ -89,7 +86,16 @@ class Transfer < Struct.new(:debet, :credit)
|
|
89
86
|
end
|
90
87
|
```
|
91
88
|
|
92
|
-
|
89
|
+
Alternatively, you can describe validation in the block (called in the scope of instance):
|
90
|
+
|
91
|
+
```ruby
|
92
|
+
class Transfer
|
93
|
+
# ...
|
94
|
+
validate { invalid :inconsistent if credit.sum != debet.sum }
|
95
|
+
end
|
96
|
+
```
|
97
|
+
|
98
|
+
The `#invalid` method translates its argument in a current class scope and raises an exception with that method.
|
93
99
|
|
94
100
|
```yaml
|
95
101
|
# config/locales/en.yml
|
@@ -101,16 +107,7 @@ en:
|
|
101
107
|
inconsistent: "Credit differs from debet by %{fraud}"
|
102
108
|
```
|
103
109
|
|
104
|
-
|
105
|
-
|
106
|
-
```ruby
|
107
|
-
class Transfer
|
108
|
-
# ...
|
109
|
-
validate { invalid :inconsistent if credit.sum != debet.sum }
|
110
|
-
end
|
111
|
-
```
|
112
|
-
|
113
|
-
To run validations use the `#validate` instance method:
|
110
|
+
To run validations use the `#validate!` instance method:
|
114
111
|
|
115
112
|
```ruby
|
116
113
|
debet = OpenStruct.new(sum: 100)
|
@@ -118,14 +115,25 @@ credit = OpenStruct.new(sum: 90)
|
|
118
115
|
fraud_transfer = Transfer.new(debet, credit)
|
119
116
|
|
120
117
|
begin
|
121
|
-
transfer.validate
|
122
|
-
rescue => error
|
118
|
+
transfer.validate! # with the bang
|
119
|
+
rescue Attestor::InvalidError => error
|
123
120
|
error.object == transfer # => true
|
124
|
-
error.messages
|
125
|
-
# => ["Credit differs from debet by 10"]
|
121
|
+
error.messages # => ["Credit differs from debet by 10"]
|
126
122
|
end
|
127
123
|
```
|
128
124
|
|
125
|
+
Another option is to use the safe version `#validate`. It rescues from the exception and returns results in a separate report object:
|
126
|
+
|
127
|
+
```ruby
|
128
|
+
report = transfer.validate # without the bang
|
129
|
+
|
130
|
+
report.valid? # => false
|
131
|
+
report.invalid? # => true
|
132
|
+
report.object == transfer # => true
|
133
|
+
report.messages # => ["Credit differs from debet by 10"]
|
134
|
+
report.error # => <Attestor::InvalidError ...>
|
135
|
+
```
|
136
|
+
|
129
137
|
Use of Contexts
|
130
138
|
---------------
|
131
139
|
|
@@ -134,43 +142,42 @@ Sometimes you need to validate the object agaist the subset of validations, not
|
|
134
142
|
To do this use `:except` and `:only` options of the `.validate` class method.
|
135
143
|
|
136
144
|
```ruby
|
137
|
-
class Transfer
|
138
|
-
|
139
|
-
|
145
|
+
class Transfer
|
146
|
+
# ...
|
140
147
|
validate :consistent, except: :steal_of_money
|
141
148
|
end
|
142
149
|
```
|
143
150
|
|
144
|
-
Then call a validate
|
151
|
+
Then call a `#validate!`/`#validate` methods with that context:
|
145
152
|
|
146
153
|
```ruby
|
147
|
-
fraud_transfer.validate # => InvalidError
|
148
|
-
fraud_transfer.validate :steal_of_money # => PASSES!
|
154
|
+
fraud_transfer.validate! # => InvalidError
|
155
|
+
fraud_transfer.validate! :steal_of_money # => PASSES!
|
149
156
|
```
|
150
157
|
|
151
|
-
You can use the same validator several times with different contexts.
|
158
|
+
You can use the same validator several times with different contexts.
|
152
159
|
|
153
160
|
```ruby
|
154
161
|
class Transfer
|
155
162
|
# ...
|
163
|
+
|
164
|
+
# validate :consistent, only: [:fair_trade, :legal]
|
156
165
|
validate :consistent, only: :fair_trade
|
157
166
|
validate :consistent, only: :legal
|
158
167
|
|
159
|
-
# This is the same as:
|
160
|
-
# validate :consistent, only: [:fair_trade, :legal]
|
161
168
|
end
|
162
169
|
```
|
163
170
|
|
164
171
|
Delegation
|
165
172
|
----------
|
166
173
|
|
167
|
-
Extract validator to
|
174
|
+
Extract validator to an external object (policy), that responds to `validate!`.
|
168
175
|
|
169
176
|
```ruby
|
170
|
-
|
177
|
+
ConsistentTransfer = Struct.new(:debet, :credit) do
|
171
178
|
include Attestor::Validations
|
172
179
|
|
173
|
-
def validate
|
180
|
+
def validate!
|
174
181
|
invalid :inconsistent unless debet.sum == credit.sum
|
175
182
|
end
|
176
183
|
end
|
@@ -197,36 +204,36 @@ class Transfer
|
|
197
204
|
end
|
198
205
|
```
|
199
206
|
|
200
|
-
The
|
201
|
-
*
|
202
|
-
*
|
207
|
+
The difference between `.validate :something` and `.validates :something` class methods is that:
|
208
|
+
* `.validate` expects `#something` to make checks and raise error by itself
|
209
|
+
* `.validates` expects `#something` to respond to `#validate!`
|
203
210
|
|
204
211
|
Policy Objects
|
205
212
|
--------------
|
206
213
|
|
207
|
-
Basically the policy includes `Attestor::Validations` with additional methods to allow
|
214
|
+
Basically the policy includes `Attestor::Validations` with additional methods to allow logical compositions.
|
208
215
|
|
209
|
-
To create a policy as a `Struct` use the builder
|
216
|
+
To create a policy as a `Struct` use the builder:
|
210
217
|
|
211
218
|
```ruby
|
212
219
|
ConsistencyPolicy = Attestor::Policy.new(:debet, :credit) do
|
213
|
-
def validate
|
220
|
+
def validate!
|
214
221
|
fraud = credit - debet
|
215
222
|
invalid :inconsistent, fraud: fraud if fraud != 0
|
216
223
|
end
|
217
224
|
end
|
218
225
|
```
|
219
226
|
|
220
|
-
If you doesn't need Struct
|
227
|
+
If you doesn't need `Struct`, include `Attestor::Policy` to the class and initialize its arguments somehow else:
|
221
228
|
|
222
229
|
```ruby
|
223
|
-
class ConsistencyPolicy
|
230
|
+
class ConsistencyPolicy
|
224
231
|
include Attestor::Policy
|
225
232
|
# ...
|
226
233
|
end
|
227
234
|
```
|
228
235
|
|
229
|
-
Policy objects can be used by `validates` method like other
|
236
|
+
Policy objects can be used by `validates` method like other objects that respond to `#validate!`:
|
230
237
|
|
231
238
|
```ruby
|
232
239
|
class Transfer
|
@@ -235,8 +242,6 @@ class Transfer
|
|
235
242
|
end
|
236
243
|
```
|
237
244
|
|
238
|
-
They also respond to `valid?` and `invalid?` methods (that just rescues from `vaidate` missing any error messages).
|
239
|
-
|
240
245
|
Complex Policies
|
241
246
|
----------------
|
242
247
|
|
@@ -245,27 +250,27 @@ Policies (assertions) can be combined by logical methods.
|
|
245
250
|
Suppose we have two policy objects:
|
246
251
|
|
247
252
|
```ruby
|
248
|
-
valid_policy.valid? # => true
|
249
|
-
invalid_policy.valid? # => false
|
253
|
+
valid_policy.validate.valid? # => true
|
254
|
+
invalid_policy.validate.valid? # => false
|
250
255
|
```
|
251
256
|
|
252
257
|
Use factory methods to provide compositions:
|
253
258
|
|
254
259
|
```ruby
|
255
260
|
complex_policy = valid_policy.not
|
256
|
-
complex_policy.validate # => fails
|
261
|
+
complex_policy.validate! # => fails
|
257
262
|
|
258
263
|
complex_policy = valid_policy.and(valid_policy, invalid_policy)
|
259
|
-
complex_policy.validate # => fails
|
264
|
+
complex_policy.validate! # => fails
|
260
265
|
|
261
266
|
complex_policy = invalid_policy.or(invalid_policy, valid_policy)
|
262
|
-
complex_policy.validate # => passes
|
267
|
+
complex_policy.validate! # => passes
|
263
268
|
|
264
269
|
complex_policy = valid_policy.xor(valid_poicy, valid_policy)
|
265
|
-
complex_policy.validate # => fails
|
270
|
+
complex_policy.validate! # => fails
|
266
271
|
|
267
272
|
complex_policy = valid_policy.xor(valid_poicy, invalid_policy)
|
268
|
-
complex_policy.validate # => passes
|
273
|
+
complex_policy.validate! # => passes
|
269
274
|
```
|
270
275
|
|
271
276
|
The `or`, `and` and `xor` methods called without argument(s) don't provide a policy object. They return lazy composer, expecting `#not` method.
|
@@ -294,6 +299,15 @@ Policy.not(valid_policy)
|
|
294
299
|
|
295
300
|
As before, you can use any number of policies (except for negation of a single policy) at any number of nesting.
|
296
301
|
|
302
|
+
Latest changes
|
303
|
+
--------------
|
304
|
+
|
305
|
+
### Version 2.0.0
|
306
|
+
|
307
|
+
1. The method `#validate` doesn't raise an error. It returns a validation results report. To raise an exception use the unsafe `#validate!` method (see [Basic Use](#basic-use) for details).
|
308
|
+
|
309
|
+
2. Policies doesn't have `#valid?` and `#invalid?` methods any longer. Both the methods are removed to `#validate` report.
|
310
|
+
|
297
311
|
Compatibility
|
298
312
|
-------------
|
299
313
|
|
data/config/metrics/rubocop.yml
CHANGED
@@ -2,20 +2,9 @@
|
|
2
2
|
|
3
3
|
module Attestor
|
4
4
|
|
5
|
-
# The exception to be raised when
|
5
|
+
# The exception to be raised when an unsafe validation fails
|
6
6
|
class InvalidError < RuntimeError
|
7
7
|
|
8
|
-
# @!scope class
|
9
|
-
# @!method new(object, messages = nil)
|
10
|
-
# Creates an exception for given object
|
11
|
-
#
|
12
|
-
# @param [Object] object
|
13
|
-
# The invalid object
|
14
|
-
# @param [String, Array<String>] messages
|
15
|
-
# The list of validation error messages
|
16
|
-
#
|
17
|
-
# @return [Attestor::InvalidError]
|
18
|
-
|
19
8
|
# @private
|
20
9
|
def initialize(object, messages = nil)
|
21
10
|
@object = object
|
data/lib/attestor/policy/and.rb
CHANGED
@@ -4,27 +4,10 @@ module Attestor
|
|
4
4
|
|
5
5
|
module Policy
|
6
6
|
|
7
|
-
#
|
8
|
-
#
|
9
|
-
# The policy is valid if all its branches are valid.
|
10
|
-
#
|
11
|
-
# @example (see #validate)
|
12
|
-
#
|
13
|
-
# @api private
|
7
|
+
# @private
|
14
8
|
class And < Node
|
15
9
|
|
16
|
-
|
17
|
-
#
|
18
|
-
# @example
|
19
|
-
# first.valid? # => true
|
20
|
-
# second.valid? # => false
|
21
|
-
#
|
22
|
-
# composition = Attestor::Policy::And.new(first, second)
|
23
|
-
# composition.validate
|
24
|
-
# # => Policy::InvalidError
|
25
|
-
#
|
26
|
-
# @return [undefined]
|
27
|
-
def validate
|
10
|
+
def validate!
|
28
11
|
return unless detect(&:invalid?)
|
29
12
|
super
|
30
13
|
end
|
@@ -4,47 +4,20 @@ module Attestor
|
|
4
4
|
|
5
5
|
module Policy
|
6
6
|
|
7
|
-
#
|
8
|
-
#
|
9
|
-
# @api private
|
7
|
+
# @private
|
10
8
|
class Negator
|
11
9
|
|
12
|
-
# @!scope class
|
13
|
-
# @!method new(policy, composer)
|
14
|
-
# Creates the negator object, expecting {#not} method call
|
15
|
-
#
|
16
|
-
# @param [Policy::Base] policy
|
17
|
-
# the policy to be composed with negations of other policies
|
18
|
-
# @param [Class] composer
|
19
|
-
# the composer for policies
|
20
|
-
#
|
21
|
-
# @return [Policy::Base::Negator]
|
22
10
|
def initialize(composer, policy)
|
23
11
|
@policy = policy
|
24
12
|
@composer = composer
|
25
13
|
freeze
|
26
14
|
end
|
27
15
|
|
28
|
-
# Returns a composition of the {#policy} with negations of other policies
|
29
|
-
#
|
30
|
-
# @param [Policy::Base, Array<Policy::Base>] policies
|
31
|
-
#
|
32
|
-
# @return [Policy::Base]
|
33
16
|
def not(*policies)
|
34
17
|
composer.new policy, policies.flat_map(&Not.method(:new))
|
35
18
|
end
|
36
19
|
|
37
|
-
|
38
|
-
# The the policy to be composed with negations of other policies
|
39
|
-
#
|
40
|
-
# @return [Policy::Base]
|
41
|
-
attr_reader :policy
|
42
|
-
|
43
|
-
# @!attribute [r] composer
|
44
|
-
# The the composer for policies
|
45
|
-
#
|
46
|
-
# @return [Class]
|
47
|
-
attr_reader :composer
|
20
|
+
attr_reader :policy, :composer
|
48
21
|
|
49
22
|
end # class Negator
|
50
23
|
|
data/lib/attestor/policy/node.rb
CHANGED
@@ -4,49 +4,23 @@ module Attestor
|
|
4
4
|
|
5
5
|
module Policy
|
6
6
|
|
7
|
-
#
|
8
|
-
#
|
9
|
-
# @api private
|
7
|
+
# @private
|
10
8
|
class Node
|
11
|
-
include Attestor::Policy
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
# @!method new(*branches)
|
16
|
-
# Creates the node with branches
|
17
|
-
#
|
18
|
-
# @param [<Attestor::Policy>, Array<Attestor::Policy>] branches
|
19
|
-
#
|
20
|
-
# @return [Policy::Base::Node]
|
21
|
-
|
22
|
-
# @private
|
9
|
+
include Attestor::Policy, Enumerable
|
10
|
+
|
11
|
+
attr_reader :branches
|
12
|
+
|
23
13
|
def initialize(*branches)
|
24
14
|
@branches = branches.flatten
|
25
15
|
freeze
|
26
16
|
end
|
27
17
|
|
28
|
-
|
29
|
-
# The branches of the node
|
30
|
-
#
|
31
|
-
# @return [Array<Policy::Base>]
|
32
|
-
attr_reader :branches
|
33
|
-
|
34
|
-
# Validates the policy as invalid
|
35
|
-
#
|
36
|
-
# To be reloaded by subclasses (And, Or, Xor, Not)
|
37
|
-
#
|
38
|
-
# @raise [Policy::InvalidError]
|
39
|
-
#
|
40
|
-
# @return [undefined]
|
41
|
-
def validate
|
18
|
+
def validate!
|
42
19
|
invalid :base
|
43
20
|
end
|
44
21
|
|
45
|
-
# Iterates throught branches
|
46
|
-
#
|
47
|
-
# @return [Enumerator]
|
48
22
|
def each
|
49
|
-
block_given? ? branches.each { |item| yield(item) } : to_enum
|
23
|
+
block_given? ? branches.each { |item| yield(item.validate) } : to_enum
|
50
24
|
end
|
51
25
|
|
52
26
|
end # class Node
|
data/lib/attestor/policy/not.rb
CHANGED
@@ -4,39 +4,14 @@ module Attestor
|
|
4
4
|
|
5
5
|
module Policy
|
6
6
|
|
7
|
-
#
|
8
|
-
#
|
9
|
-
# The policy is valid if its only branch is invalid
|
10
|
-
#
|
11
|
-
# @example (see #validate)
|
12
|
-
#
|
13
|
-
# @api private
|
7
|
+
# @private
|
14
8
|
class Not < Node
|
15
9
|
|
16
|
-
# @!scope class
|
17
|
-
# @!method new(policy)
|
18
|
-
# Creates the policy negation
|
19
|
-
#
|
20
|
-
# @param [Array<Policy::Base>] policy
|
21
|
-
#
|
22
|
-
# @return [Policy::Base::Node]
|
23
|
-
|
24
|
-
# @private
|
25
10
|
def initialize(_)
|
26
11
|
super
|
27
12
|
end
|
28
13
|
|
29
|
-
|
30
|
-
#
|
31
|
-
# @example
|
32
|
-
# policy.valid? # => true
|
33
|
-
#
|
34
|
-
# composition = Attestor::Policy::Not.new(policy)
|
35
|
-
# composition.validate
|
36
|
-
# # => Policy::InvalidError
|
37
|
-
#
|
38
|
-
# @return [undefined]
|
39
|
-
def validate
|
14
|
+
def validate!
|
40
15
|
return unless detect(&:valid?)
|
41
16
|
super
|
42
17
|
end
|
data/lib/attestor/policy/or.rb
CHANGED
@@ -4,27 +4,10 @@ module Attestor
|
|
4
4
|
|
5
5
|
module Policy
|
6
6
|
|
7
|
-
#
|
8
|
-
#
|
9
|
-
# The policy is valid unless all its branches are invalid.
|
10
|
-
#
|
11
|
-
# @example (see #validate)
|
12
|
-
#
|
13
|
-
# @api private
|
7
|
+
# @private
|
14
8
|
class Or < Node
|
15
9
|
|
16
|
-
|
17
|
-
#
|
18
|
-
# @example
|
19
|
-
# first.valid? # => false
|
20
|
-
# second.valid? # => false
|
21
|
-
#
|
22
|
-
# composition = Attestor::Policy::Or.new(first, second)
|
23
|
-
# composition.validate
|
24
|
-
# # => Policy::InvalidError
|
25
|
-
#
|
26
|
-
# @return [undefined]
|
27
|
-
def validate
|
10
|
+
def validate!
|
28
11
|
return if detect(&:valid?)
|
29
12
|
super
|
30
13
|
end
|
data/lib/attestor/policy/xor.rb
CHANGED
@@ -4,27 +4,10 @@ module Attestor
|
|
4
4
|
|
5
5
|
module Policy
|
6
6
|
|
7
|
-
#
|
8
|
-
#
|
9
|
-
# The policy is valid when it has both valid and invalid branches.
|
10
|
-
#
|
11
|
-
# @example (see #validate)
|
12
|
-
#
|
13
|
-
# @api private
|
7
|
+
# @private
|
14
8
|
class Xor < Node
|
15
9
|
|
16
|
-
|
17
|
-
#
|
18
|
-
# @example
|
19
|
-
# first.valid? # => true
|
20
|
-
# second.valid? # => true
|
21
|
-
#
|
22
|
-
# composition = Attestor::Policy::Xor.new(first, second)
|
23
|
-
# composition.validate
|
24
|
-
# # => Policy::InvalidError
|
25
|
-
#
|
26
|
-
# @return [undefined]
|
27
|
-
def validate
|
10
|
+
def validate!
|
28
11
|
return if detect(&:valid?) && detect(&:invalid?)
|
29
12
|
super
|
30
13
|
end
|
data/lib/attestor/policy.rb
CHANGED
@@ -36,24 +36,6 @@ module Attestor
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
-
# Checks whether the policy is valid
|
40
|
-
#
|
41
|
-
# @return [Boolean]
|
42
|
-
def valid?
|
43
|
-
validate
|
44
|
-
rescue InvalidError
|
45
|
-
false
|
46
|
-
else
|
47
|
-
true
|
48
|
-
end
|
49
|
-
|
50
|
-
# Checks whether the policy is invalid
|
51
|
-
#
|
52
|
-
# @return [Boolean]
|
53
|
-
def invalid?
|
54
|
-
!valid?
|
55
|
-
end
|
56
|
-
|
57
39
|
# Negates the current policy
|
58
40
|
#
|
59
41
|
# @return [Attestor::Policy::Not]
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Attestor
|
4
|
+
|
5
|
+
# Describes the result, returned by safe validation
|
6
|
+
class Report
|
7
|
+
|
8
|
+
# @private
|
9
|
+
def initialize(object, error = nil)
|
10
|
+
@object = object
|
11
|
+
@error = error
|
12
|
+
freeze
|
13
|
+
end
|
14
|
+
|
15
|
+
# @!attribute [r] object
|
16
|
+
# The object being validated
|
17
|
+
#
|
18
|
+
# @return [Object]
|
19
|
+
attr_reader :object
|
20
|
+
|
21
|
+
# @!attribute [r] error
|
22
|
+
# The exception raised by validation
|
23
|
+
#
|
24
|
+
# @return [Attestor::InvalidError] if validation fails
|
25
|
+
# @return [nil] if validation passes
|
26
|
+
attr_reader :error
|
27
|
+
|
28
|
+
# Checks whether validation passes
|
29
|
+
#
|
30
|
+
# @return [Boolean]
|
31
|
+
def valid?
|
32
|
+
error.blank?
|
33
|
+
end
|
34
|
+
|
35
|
+
# Checks whether validation fails
|
36
|
+
#
|
37
|
+
# @return [Boolean]
|
38
|
+
def invalid?
|
39
|
+
!valid?
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns the list of error messages
|
43
|
+
#
|
44
|
+
# @return [Array<String>]
|
45
|
+
def messages
|
46
|
+
error ? error.messages : []
|
47
|
+
end
|
48
|
+
|
49
|
+
end # class Report
|
50
|
+
|
51
|
+
end # module Attestor
|
@@ -4,26 +4,11 @@ module Attestor
|
|
4
4
|
|
5
5
|
module Validations
|
6
6
|
|
7
|
-
#
|
8
|
-
#
|
9
|
-
# The follower not only calls an instance method (block) as validator does,
|
10
|
-
# but calls #validate method of the result.
|
11
|
-
#
|
12
|
-
# @example
|
13
|
-
# follower = Validator.new(:foo, only: :baz) { FooPolicy.new(foo) }
|
14
|
-
#
|
15
|
-
# @api private
|
7
|
+
# @private
|
16
8
|
class Delegator < Validator
|
17
9
|
|
18
|
-
|
19
|
-
|
20
|
-
# @param [Object] object
|
21
|
-
#
|
22
|
-
# @raise [Attestor::InvalidError] if a policy isn't valid
|
23
|
-
#
|
24
|
-
# @return [undefined]
|
25
|
-
def validate(_)
|
26
|
-
super.validate
|
10
|
+
def validate!(_)
|
11
|
+
super.validate!
|
27
12
|
end
|
28
13
|
|
29
14
|
end # class Follower
|
@@ -4,24 +4,9 @@ module Attestor
|
|
4
4
|
|
5
5
|
module Validations
|
6
6
|
|
7
|
-
#
|
8
|
-
#
|
9
|
-
# @api private
|
7
|
+
# @private
|
10
8
|
class Message < String
|
11
9
|
|
12
|
-
# @!scope class
|
13
|
-
# @!method new(value, object, options = {})
|
14
|
-
# Builds a string from value
|
15
|
-
#
|
16
|
-
# @param [#to_s] value
|
17
|
-
# @param [Object] object
|
18
|
-
# @param [Hash] options
|
19
|
-
# options for translating symbolic value
|
20
|
-
#
|
21
|
-
# @return [String]
|
22
|
-
# either translation of symbolic value or stringified value argument
|
23
|
-
|
24
|
-
# @private
|
25
10
|
def initialize(value, object, options = {})
|
26
11
|
@value = value
|
27
12
|
@object = object
|