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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 24226b6df180842850c926be63af60c33803e6e0
4
- data.tar.gz: 1764202eb7a457a16bde2590b25909af05d4d17b
3
+ metadata.gz: 63f4151b5dc72b051cea9b0c448472007841deaa
4
+ data.tar.gz: a0f4c037e605fd4ca96e6c1d8518accaee6d9509
5
5
  SHA512:
6
- metadata.gz: abef4e5a06756f1f32db42e60e0358451d524620ea0d7dc21af6f4929da5eea21f86a74a9930142164b219ba68ecb362cefe6f7115baffda67ba93a2477d7ec2
7
- data.tar.gz: d67597321bb8c496167825f17b558c2e0e6e02b2bd75064eee1a7126146d2ffa0ecdb42742f5f912c19cce4ee45c5ef43e6d81158a5081dfbda353bab9960a09
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.send :validates_each, field do |record, attr, value|
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.send :validates_each, field do |record, attr, value|
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.send :define_init, field, type || Array
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.send :define_multiple_accessor, field
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
@@ -1,10 +1,24 @@
1
1
  module Eapi
2
- class TypeChecker < Struct.new(:given_type)
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
@@ -1,3 +1,3 @@
1
1
  module Eapi
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
@@ -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
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eapi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eduardo Turiño