eapi 0.2.0 → 0.2.1
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/README.md +81 -0
- data/lib/eapi/definition_runners/list.rb +9 -0
- data/lib/eapi/definition_runners/property.rb +13 -10
- data/lib/eapi/definition_runners/runner.rb +33 -1
- data/lib/eapi/methods/properties.rb +30 -0
- data/lib/eapi/type_checker.rb +20 -2
- data/lib/eapi/version.rb +1 -1
- data/spec/list_spec.rb +40 -0
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 63f4151b5dc72b051cea9b0c448472007841deaa
|
4
|
+
data.tar.gz: a0f4c037e605fd4ca96e6c1d8518accaee6d9509
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b06d56359371a02be843a0bc48b11f8fb9c873656e08d7d877427c95840d58b1595ea07d0faa1c9a176a7cfbb2432a2b67e74ace65f113c0836c51bde87d0147
|
7
|
+
data.tar.gz: 24e712cec447d69b9a65202b946d6a73e23aaa35334c0e92b46a9aba15fa119245e6cde824da3c0a34c9daff0dbf3e233e8747f7061dbc44c73aebedba855858
|
data/README.md
CHANGED
@@ -316,6 +316,87 @@ eapi.something # => {}
|
|
316
316
|
|
317
317
|
To trigger the error, the value must not be an instance of the given Type, and also must not respond `true` to `value.is?(type)`
|
318
318
|
|
319
|
+
#### Skip type validation with 'raw' values with `allow_raw` option
|
320
|
+
|
321
|
+
If we want to check for the type of the elements, but still want the flexibility of using raw `Hash` or `Array` in case we want something specific there, we can specify it with the `allow_raw` option.
|
322
|
+
|
323
|
+
With this, eapi will let you skip the type validation when the value is either a `Hash` or an `Array`, assuming that "you know what you are doing".
|
324
|
+
|
325
|
+
```ruby
|
326
|
+
class ValueKlass
|
327
|
+
include Eapi::Item
|
328
|
+
|
329
|
+
property :value
|
330
|
+
end
|
331
|
+
|
332
|
+
class TestKlass
|
333
|
+
include Eapi::Item
|
334
|
+
|
335
|
+
property :something, type: ValueKlass, allow_raw: true
|
336
|
+
property :somelist, multiple: true, element_type: ValueKlass, allow_raw: true
|
337
|
+
end
|
338
|
+
|
339
|
+
class TestList
|
340
|
+
include Eapi::List
|
341
|
+
|
342
|
+
elements type: ValueKlass, allow_raw: true
|
343
|
+
end
|
344
|
+
|
345
|
+
i = TestKlass.new
|
346
|
+
i.something 1
|
347
|
+
i.valid? # => false
|
348
|
+
|
349
|
+
i.something ValueKlass.new
|
350
|
+
i.valid? # => true
|
351
|
+
|
352
|
+
i.something({some: :hash})
|
353
|
+
i.valid? # => true
|
354
|
+
|
355
|
+
i.add_somelist 1
|
356
|
+
i.valid? # => false
|
357
|
+
|
358
|
+
i.clear_somelist.add_somelist({a: :hash}).add_somelist([:an, :array])
|
359
|
+
i.valid? # => true
|
360
|
+
|
361
|
+
l = TestList.new
|
362
|
+
l.add 1
|
363
|
+
l.valid? # => false
|
364
|
+
|
365
|
+
i.clear.add(ValueKlass.new).add({a: :hash}).add([:an, :array])
|
366
|
+
l.valid? # => true
|
367
|
+
```
|
368
|
+
|
369
|
+
You can also enable this option after defining the property, with the `property_allow_raw` and `property_disallow_raw` methods and check if it is enabled with `property_allow_raw?`. In `List`s, the methods are `elements_allow_raw`, `elements_disallow_raw` and `elements_allow_raw?`.
|
370
|
+
|
371
|
+
```ruby
|
372
|
+
class TestKlass
|
373
|
+
include Eapi::Item
|
374
|
+
|
375
|
+
property :something, type: ValueKlass
|
376
|
+
end
|
377
|
+
|
378
|
+
TestKlass.property_allow_raw?(:something) # => false
|
379
|
+
|
380
|
+
TestKlass.property_allow_raw(:something)
|
381
|
+
TestKlass.property_allow_raw?(:something) # => true
|
382
|
+
|
383
|
+
TestKlass.property_disallow_raw(:something)
|
384
|
+
TestKlass.property_allow_raw?(:something) # => false
|
385
|
+
|
386
|
+
class TestList
|
387
|
+
include Eapi::List
|
388
|
+
elements type: ValueKlass
|
389
|
+
end
|
390
|
+
|
391
|
+
TestList.elements_allow_raw? # => false
|
392
|
+
|
393
|
+
TestList.elements_allow_raw
|
394
|
+
TestList.elements_allow_raw? # => true
|
395
|
+
|
396
|
+
TestList.elements_disallow_raw
|
397
|
+
TestList.elements_allow_raw? # => false
|
398
|
+
```
|
399
|
+
|
319
400
|
#### Custom validation with `validate_with` option
|
320
401
|
|
321
402
|
A more specific validation can be used using `validate_with`, that works the same way as `ActiveModel::Validations`.
|
@@ -13,6 +13,7 @@ module Eapi
|
|
13
13
|
run_validate_element_type
|
14
14
|
run_validate_element_with
|
15
15
|
run_validate_uniqueness
|
16
|
+
run_allow_raw
|
16
17
|
end
|
17
18
|
|
18
19
|
def run_validate_uniqueness
|
@@ -39,6 +40,10 @@ module Eapi
|
|
39
40
|
end
|
40
41
|
end
|
41
42
|
|
43
|
+
def run_allow_raw
|
44
|
+
Runner.allow_raw(klass: klass, field: :_list, allow_raw: allow_raw?)
|
45
|
+
end
|
46
|
+
|
42
47
|
def required?
|
43
48
|
definition.fetch(:required, false)
|
44
49
|
end
|
@@ -54,6 +59,10 @@ module Eapi
|
|
54
59
|
def element_type
|
55
60
|
definition.fetch(:element_type, nil) || definition.fetch(:type, nil)
|
56
61
|
end
|
62
|
+
|
63
|
+
def allow_raw?
|
64
|
+
definition.fetch(:allow_raw, false)
|
65
|
+
end
|
57
66
|
end
|
58
67
|
|
59
68
|
end
|
@@ -6,6 +6,7 @@ module Eapi
|
|
6
6
|
run_multiple_accessor
|
7
7
|
run_init
|
8
8
|
run_validations
|
9
|
+
run_allow_raw
|
9
10
|
end
|
10
11
|
|
11
12
|
private
|
@@ -37,31 +38,29 @@ module Eapi
|
|
37
38
|
|
38
39
|
def run_validate_type
|
39
40
|
if type
|
40
|
-
klass
|
41
|
-
unless Eapi::TypeChecker.new(type).is_valid_type?(value)
|
42
|
-
record.errors.add(attr, "must be a #{type}")
|
43
|
-
end
|
44
|
-
end
|
41
|
+
Runner.validate_type(klass: klass, field: field, type: type)
|
45
42
|
end
|
46
43
|
end
|
47
44
|
|
48
45
|
def run_validate_with
|
49
46
|
if validate_with
|
50
|
-
klass
|
51
|
-
validate_with.call(record, attr, value)
|
52
|
-
end
|
47
|
+
Runner.validate_with(klass: klass, field: field, validate_with: validate_with)
|
53
48
|
end
|
54
49
|
end
|
55
50
|
|
51
|
+
def run_allow_raw
|
52
|
+
Runner.allow_raw(klass: klass, field: field, allow_raw: allow_raw?)
|
53
|
+
end
|
54
|
+
|
56
55
|
def run_init
|
57
56
|
if type || multiple?
|
58
|
-
klass
|
57
|
+
Runner.init(klass: klass, field: field, type: type || Array)
|
59
58
|
end
|
60
59
|
end
|
61
60
|
|
62
61
|
def run_multiple_accessor
|
63
62
|
if multiple?
|
64
|
-
klass
|
63
|
+
Runner.multiple_accessor(klass: klass, field: field)
|
65
64
|
end
|
66
65
|
end
|
67
66
|
|
@@ -95,6 +94,10 @@ module Eapi
|
|
95
94
|
def type
|
96
95
|
definition.fetch(:type, nil)
|
97
96
|
end
|
97
|
+
|
98
|
+
def allow_raw?
|
99
|
+
definition.fetch(:allow_raw, false)
|
100
|
+
end
|
98
101
|
end
|
99
102
|
end
|
100
103
|
end
|
@@ -11,11 +11,27 @@ module Eapi
|
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
+
def self.validate_type(klass:, field:, type:)
|
15
|
+
klass.send :validates_each, field do |record, attr, value|
|
16
|
+
allow_raw = klass.property_allow_raw?(field)
|
17
|
+
unless Eapi::TypeChecker.new(type, allow_raw).is_valid_type?(value)
|
18
|
+
record.errors.add(attr, "must be a #{type}")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.validate_with(klass:, field:, validate_with:)
|
24
|
+
klass.send :validates_each, field do |record, attr, value|
|
25
|
+
validate_with.call(record, attr, value)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
14
29
|
def self.validate_element_type(klass:, field:, element_type:)
|
15
30
|
klass.send :validates_each, field do |record, attr, value|
|
31
|
+
allow_raw = klass.property_allow_raw?(field)
|
16
32
|
if value.respond_to?(:each)
|
17
33
|
value.each do |v|
|
18
|
-
unless Eapi::TypeChecker.new(element_type).is_valid_type?(v)
|
34
|
+
unless Eapi::TypeChecker.new(element_type, allow_raw).is_valid_type?(v)
|
19
35
|
record.errors.add(attr, "element must be a #{element_type}")
|
20
36
|
end
|
21
37
|
end
|
@@ -39,6 +55,22 @@ module Eapi
|
|
39
55
|
end
|
40
56
|
end
|
41
57
|
end
|
58
|
+
|
59
|
+
def self.allow_raw(klass:, field:, allow_raw:)
|
60
|
+
if allow_raw
|
61
|
+
klass.send :property_allow_raw, field
|
62
|
+
else
|
63
|
+
klass.send :property_disallow_raw, field
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.init(klass:, field:, type:)
|
68
|
+
klass.send :define_init, field, type
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.multiple_accessor(klass:, field:)
|
72
|
+
klass.send :define_multiple_accessor, field
|
73
|
+
end
|
42
74
|
end
|
43
75
|
end
|
44
76
|
end
|
@@ -28,6 +28,24 @@ module Eapi
|
|
28
28
|
end
|
29
29
|
|
30
30
|
module ClassMethods
|
31
|
+
def property_allow_raw(field)
|
32
|
+
@_property_allow_raw ||= {}
|
33
|
+
|
34
|
+
@_property_allow_raw[field.to_sym] = true
|
35
|
+
end
|
36
|
+
|
37
|
+
def property_disallow_raw(field)
|
38
|
+
@_property_allow_raw ||= {}
|
39
|
+
|
40
|
+
@_property_allow_raw[field.to_sym] = false
|
41
|
+
end
|
42
|
+
|
43
|
+
def property_allow_raw?(field)
|
44
|
+
@_property_allow_raw ||= {}
|
45
|
+
|
46
|
+
@_property_allow_raw.fetch(field.to_sym, false)
|
47
|
+
end
|
48
|
+
|
31
49
|
def property(field, definition = {})
|
32
50
|
fs = field.to_sym
|
33
51
|
define_accessors fs
|
@@ -58,6 +76,18 @@ module Eapi
|
|
58
76
|
end
|
59
77
|
|
60
78
|
module ListCLassMethods
|
79
|
+
def elements_allow_raw
|
80
|
+
property_allow_raw(:_list)
|
81
|
+
end
|
82
|
+
|
83
|
+
def elements_disallow_raw
|
84
|
+
property_disallow_raw(:_list)
|
85
|
+
end
|
86
|
+
|
87
|
+
def elements_allow_raw?
|
88
|
+
property_allow_raw?(:_list)
|
89
|
+
end
|
90
|
+
|
61
91
|
def elements(definition)
|
62
92
|
run_list_definition definition
|
63
93
|
store_list_definition definition
|
data/lib/eapi/type_checker.rb
CHANGED
@@ -1,10 +1,24 @@
|
|
1
1
|
module Eapi
|
2
|
-
class TypeChecker
|
2
|
+
class TypeChecker
|
3
|
+
|
4
|
+
attr_reader :given_type, :allow_raw
|
5
|
+
|
6
|
+
def initialize(given_type, allow_raw = false)
|
7
|
+
@given_type = given_type
|
8
|
+
@allow_raw = allow_raw
|
9
|
+
end
|
10
|
+
|
3
11
|
def is_valid_type?(value)
|
4
|
-
value.nil? || is_same_type?(value) || poses_as_type?(value)
|
12
|
+
value.nil? || is_same_type?(value) || poses_as_type?(value) || valid_raw?(value)
|
5
13
|
end
|
6
14
|
|
7
15
|
private
|
16
|
+
def valid_raw?(value)
|
17
|
+
return false unless allow_raw?
|
18
|
+
|
19
|
+
value.kind_of?(Array) || value.kind_of?(Hash)
|
20
|
+
end
|
21
|
+
|
8
22
|
def is_same_type?(value)
|
9
23
|
value.kind_of?(type)
|
10
24
|
end
|
@@ -20,5 +34,9 @@ module Eapi
|
|
20
34
|
given_type.to_s.constantize
|
21
35
|
end
|
22
36
|
end
|
37
|
+
|
38
|
+
def allow_raw?
|
39
|
+
allow_raw
|
40
|
+
end
|
23
41
|
end
|
24
42
|
end
|
data/lib/eapi/version.rb
CHANGED
data/spec/list_spec.rb
CHANGED
@@ -373,6 +373,46 @@ RSpec.describe Eapi do
|
|
373
373
|
subject.add "Many Strings"
|
374
374
|
expect(subject).to be_valid
|
375
375
|
end
|
376
|
+
|
377
|
+
context 'with option allow_raw (default false)' do
|
378
|
+
class AllowRawValueKlass
|
379
|
+
include Eapi::Item
|
380
|
+
property :something
|
381
|
+
end
|
382
|
+
|
383
|
+
class ListAllowRawTestKlass
|
384
|
+
include Eapi::List
|
385
|
+
|
386
|
+
elements type: AllowRawValueKlass, allow_raw: true
|
387
|
+
end
|
388
|
+
|
389
|
+
subject { ListAllowRawTestKlass.new }
|
390
|
+
|
391
|
+
it 'allows a Hash or Array value with type check' do
|
392
|
+
subject.add(1)
|
393
|
+
expect(subject).not_to be_valid
|
394
|
+
|
395
|
+
subject.clear.add(AllowRawValueKlass.new)
|
396
|
+
expect(subject).to be_valid
|
397
|
+
|
398
|
+
subject.clear.add([1, 2, 3]).add({a: :hash})
|
399
|
+
expect(subject).to be_valid
|
400
|
+
end
|
401
|
+
|
402
|
+
it 'can be allowed and disallowed after definition' do
|
403
|
+
orig = ListAllowRawTestKlass.elements_allow_raw?
|
404
|
+
ListAllowRawTestKlass.elements_allow_raw
|
405
|
+
expect(ListAllowRawTestKlass).to be_elements_allow_raw
|
406
|
+
ListAllowRawTestKlass.elements_disallow_raw
|
407
|
+
expect(ListAllowRawTestKlass).not_to be_elements_allow_raw
|
408
|
+
|
409
|
+
if orig
|
410
|
+
ListAllowRawTestKlass.elements_allow_raw
|
411
|
+
else
|
412
|
+
ListAllowRawTestKlass.elements_disallow_raw
|
413
|
+
end
|
414
|
+
end
|
415
|
+
end
|
376
416
|
end
|
377
417
|
|
378
418
|
context 'unique' do
|