eapi 0.3.0 → 0.4.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/README.md +195 -167
- data/lib/eapi.rb +1 -0
- data/lib/eapi/common.rb +5 -0
- data/lib/eapi/item.rb +9 -7
- data/lib/eapi/list.rb +9 -7
- data/lib/eapi/methods/accessor.rb +6 -1
- data/lib/eapi/methods/properties.rb +9 -1
- data/lib/eapi/value_ignore_checker.rb +28 -0
- data/lib/eapi/version.rb +1 -1
- data/spec/ignore_spec.rb +178 -0
- data/spec/{to_h_spec.rb → render_spec.rb} +24 -2
- metadata +7 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c1be90f666a6468f4f4e574b85edcf706d7336a7
|
4
|
+
data.tar.gz: c485bbe47dbd2ff849aad2b3c7dc4a9b8521cc0a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: da17b4c132b4f45b868bf64eb1fde65faafe04e34fea500694b372aa057f7c1c21076c222e45169c7f45bdcfe5b66fed65e21bcfec86d2578f45c3fca423951a
|
7
|
+
data.tar.gz: 433e10ff4cd1bd992eef4a4779c003891d9c2f35d72e46ce4559ef83593c88b1e58731868519f538b13f63e10bf4a4f61b9e3d7b1e00f470144bdbab8ee9e46a
|
data/README.md
CHANGED
@@ -63,6 +63,201 @@ This will provide:
|
|
63
63
|
|
64
64
|
We'll se this in detail.
|
65
65
|
|
66
|
+
|
67
|
+
## Common behaviour to `Item` and `List`
|
68
|
+
|
69
|
+
The following features are shared between `List`s and `Item`s.
|
70
|
+
|
71
|
+
### Convert to hashes: `render` and `perform_render`
|
72
|
+
|
73
|
+
All Eapi objects respond to `render` and return by default a hash (for `Item` objects) or an array (for `List` objects), as it is the main purpose of this gem. It will execute any validation (see property definition), and if everything is ok, it will convert it to the simple structure.
|
74
|
+
|
75
|
+
`Item` objects will invoke `render` when receiving `to_h`, while `List` objects will do the same when receiving `to_a`.
|
76
|
+
|
77
|
+
#### Methods involved
|
78
|
+
|
79
|
+
Inside, `render` will call `valid?`, raise an error of type `Eapi::Errors::InvalidElementError` if something is not right, and if everything is ok it will call `perform_render`.
|
80
|
+
|
81
|
+
On `Item` objects, the `perform_render` method will create a hash with the properties as keys. Each value will be "converted" (see "Values conversion" section). On `List` objects, the `perform_render` will create an array, with all
|
82
|
+
|
83
|
+
#### Values conversion
|
84
|
+
|
85
|
+
By default, each property will be converted into a simple element (Array, Hash, or simple value).
|
86
|
+
|
87
|
+
1. If a value responds to `render`, it will call that method. That way, Eapi objects that are values of some properties or lists will be validated and rendered (converted) themselves (render / value conversion cascade).
|
88
|
+
2. If a value is an Array or a Set, `to_a` will be invoked and all values will be converted in the same way.
|
89
|
+
3. If a value respond to `to_h`, it will be called.
|
90
|
+
|
91
|
+
#### Ignoring values
|
92
|
+
|
93
|
+
By default, any `nil` values will be omitted in the final structure by the `perform_render` method, in both `Item` and `List`.
|
94
|
+
|
95
|
+
With the `ignore` option in the definition, that behaviour can be modified.
|
96
|
+
|
97
|
+
* `ignore: false`: that no value will be ignored
|
98
|
+
* `ignore: :blank?`: with a string or a symbol in the `ignore` option, the value will be ignored if it respond truthy to the message represented by that `ignore` option. (ie: `ignore: :blank?` => all values that return truthy to `value.blank?` will be ignored)
|
99
|
+
* `ignore: Proc|Callable|Lambda`: with a callable object in the `ignore` option, the value will be ignored if the callable object respond truthy when invoked with the value as argument.
|
100
|
+
|
101
|
+
```ruby
|
102
|
+
class ExampleItem
|
103
|
+
include Eapi::Item
|
104
|
+
|
105
|
+
# by default, ignored if value is `nil`
|
106
|
+
property :prop1
|
107
|
+
|
108
|
+
# ignored if value returns truthy to `.blank?`
|
109
|
+
property :prop2, ignore: :blank?
|
110
|
+
|
111
|
+
# never ignored
|
112
|
+
property :prop3, ignore: false
|
113
|
+
|
114
|
+
# ignored if the callable object returns true when `.call(value)` (in this case, if the value is equal to "i don't want you")
|
115
|
+
property :prop4, ignore: Proc.new {|val| val == "i don't want you"}
|
116
|
+
end
|
117
|
+
```
|
118
|
+
|
119
|
+
#### Example
|
120
|
+
|
121
|
+
To demonstrate this behaviour we'll have an Eapi enabled class `ExampleEapi` and another `ComplexValue` class that responds to `to_h`. We'll set into the `ExampleEapi` object complex properties to demonstrate the conversion into a simple structure.
|
122
|
+
|
123
|
+
```ruby
|
124
|
+
class ComplexValue
|
125
|
+
def to_h
|
126
|
+
{
|
127
|
+
a: Set.new(['hello', 'world', MyTestObject.new])
|
128
|
+
}
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
class ExampleEapi
|
133
|
+
include Eapi::Item
|
134
|
+
|
135
|
+
property :something, required: true
|
136
|
+
property :other
|
137
|
+
end
|
138
|
+
|
139
|
+
# TESTING `render`
|
140
|
+
|
141
|
+
list = Set.new [
|
142
|
+
OpenStruct.new(a: 1, 'b' => 2),
|
143
|
+
{c: 3, 'd' => 4},
|
144
|
+
nil
|
145
|
+
]
|
146
|
+
|
147
|
+
eapi = ExampleEapi.new something: list, other: ComplexValue.new
|
148
|
+
|
149
|
+
# same as eapi.to_h
|
150
|
+
eapi.render # =>
|
151
|
+
# {
|
152
|
+
# something: [
|
153
|
+
# {a: 1, b: 2},
|
154
|
+
# {c: 3, d: 4},
|
155
|
+
# ],
|
156
|
+
#
|
157
|
+
# other: {
|
158
|
+
# a: [
|
159
|
+
# 'hello',
|
160
|
+
# 'world',
|
161
|
+
# {a: 'hello'}
|
162
|
+
# ]
|
163
|
+
# }
|
164
|
+
# }
|
165
|
+
```
|
166
|
+
|
167
|
+
### Pose as other types
|
168
|
+
|
169
|
+
An Eapi class can poses as other types, for purposes of `type` checking in a property definition. We use the class method `is` for this.
|
170
|
+
|
171
|
+
the `is?` method is also available as an instance method.
|
172
|
+
|
173
|
+
Eapi also creates specific instance and class methods like `is_a_some_type?` or `is_an_another_type?`.
|
174
|
+
|
175
|
+
example:
|
176
|
+
|
177
|
+
```ruby
|
178
|
+
class SuperTestKlass
|
179
|
+
include Eapi::Item
|
180
|
+
end
|
181
|
+
|
182
|
+
class TestKlass < SuperTestKlass
|
183
|
+
is :one_thing, :other_thing, OtherType
|
184
|
+
end
|
185
|
+
|
186
|
+
TestKlass.is? TestKlass # => true
|
187
|
+
TestKlass.is? 'TestKlass' # => true
|
188
|
+
TestKlass.is? :TestKlass # => true
|
189
|
+
|
190
|
+
TestKlass.is? SuperTestKlass # => true
|
191
|
+
TestKlass.is? 'SuperTestKlass' # => true
|
192
|
+
TestKlass.is? :SuperTestKlass # => true
|
193
|
+
|
194
|
+
TestKlass.is? :one_thing # => true
|
195
|
+
TestKlass.is? :other_thing # => true
|
196
|
+
TestKlass.is? :other_thing # => true
|
197
|
+
TestKlass.is? OtherType # => true
|
198
|
+
TestKlass.is? :OtherType # => true
|
199
|
+
|
200
|
+
TestKlass.is? SomethingElse # => false
|
201
|
+
TestKlass.is? :SomethingElse # => false
|
202
|
+
|
203
|
+
# also works on instance
|
204
|
+
obj = TestKlass.new
|
205
|
+
obj.is? TestKlass # => true
|
206
|
+
obj.is? :one_thing # => true
|
207
|
+
|
208
|
+
# specific type test methods
|
209
|
+
TestKlass.is_a_test_klass? # => true
|
210
|
+
TestKlass.is_an_one_thing? # => true
|
211
|
+
TestKlass.is_a_super_duper_thing? # => false
|
212
|
+
|
213
|
+
obj.is_a_test_klass? # => true
|
214
|
+
obj.is_an_one_thing? # => true
|
215
|
+
obj.is_a_super_duper_thing? # => false
|
216
|
+
```
|
217
|
+
|
218
|
+
### Object creation shortcut: calling methods in Eapi
|
219
|
+
|
220
|
+
Calling a method with the desired class name in `Eapi` module will do the same as `DesiredClass.new(...)`. The name can be the same as the class, or an underscorised version, or a simple underscored one.
|
221
|
+
|
222
|
+
The goal is to use `Eapi.esr_search(name: 'Paco')` as a shortcut to `Esr::Search.new(name: 'Paco')`. We can also use `Eapi.Esr_Search(...)` and other combinations.
|
223
|
+
|
224
|
+
To show this feature and all the combinations for method names, we'll use the 2 example classes that are used in the actual test rspec.
|
225
|
+
|
226
|
+
```ruby
|
227
|
+
class MyTestKlassOutside
|
228
|
+
include Eapi::Item
|
229
|
+
|
230
|
+
property :something
|
231
|
+
end
|
232
|
+
|
233
|
+
module Somewhere
|
234
|
+
class TestKlassInModule
|
235
|
+
include Eapi::Item
|
236
|
+
|
237
|
+
property :something
|
238
|
+
end
|
239
|
+
end
|
240
|
+
```
|
241
|
+
|
242
|
+
As shown by rspec run:
|
243
|
+
|
244
|
+
```
|
245
|
+
initialise using method calls to Eapi
|
246
|
+
Eapi.MyTestKlassOutside(...)
|
247
|
+
calls MyTestKlassOutside.new
|
248
|
+
Eapi.my_test_klass_outside(...)
|
249
|
+
calls MyTestKlassOutside.new
|
250
|
+
Eapi.Somewhere__TestKlassInModule(...)
|
251
|
+
calls Somewhere::TestKlassInModule.new
|
252
|
+
Eapi.somewhere__test_klass_in_module(...)
|
253
|
+
calls Somewhere::TestKlassInModule.new
|
254
|
+
Eapi.Somewhere_TestKlassInModule(...)
|
255
|
+
calls Somewhere::TestKlassInModule.new
|
256
|
+
Eapi.somewhere_test_klass_in_module(...)
|
257
|
+
calls Somewhere::TestKlassInModule.new
|
258
|
+
```
|
259
|
+
|
260
|
+
|
66
261
|
## `Eapi::Item`: Property based Item objects
|
67
262
|
|
68
263
|
### `initialize` method
|
@@ -141,76 +336,6 @@ x.one # => :fluent
|
|
141
336
|
res.equal? x # => true
|
142
337
|
```
|
143
338
|
|
144
|
-
### Convert to hashes: `render`, `to_h` and `create_hash`
|
145
|
-
|
146
|
-
All Eapi classes respond to `render` and return a hash (for `Item` classes) or an array (for `List` classes), as it is the main purpose of this gem. It will execute any validation (see property definition), and if everything is ok, it will convert it to a simple hash structure.
|
147
|
-
|
148
|
-
`Item` classes will invoke `render` when receiving `to_h`, while `List` classes will do the same when receiving `to_a`
|
149
|
-
|
150
|
-
#### Methods involved
|
151
|
-
|
152
|
-
Inside, `render` will call `valid?`, raise an error of type `Eapi::Errors::InvalidElementError` if something is not right, and if everything is ok it will call `create_hash`.
|
153
|
-
|
154
|
-
The `create_hash` method will create a hash with the properties as keys. Each value will be "converted" (see "Values conversion" section).
|
155
|
-
|
156
|
-
#### Values conversion
|
157
|
-
|
158
|
-
By default, each property will be converted into a simple element (Array, Hash, or simple value).
|
159
|
-
|
160
|
-
1. If a value responds to `render`, it will call that method. That way, Eapi objects that are values of some properties or lists will be validated and rendered (converted) themselves (render / value conversion cascade).
|
161
|
-
2. If a value is an Array or a Set, `to_a` will be invoked and all values will be converted in the same way.
|
162
|
-
3. If a value respond to `to_h`, it will be called.
|
163
|
-
|
164
|
-
important: *any nil value will be omitted* in the final hash.
|
165
|
-
|
166
|
-
#### Example
|
167
|
-
|
168
|
-
To demonstrate this behaviour we'll have an Eapi enabled class `ExampleEapi` and another `ComplexValue` class that responds to `to_h`. We'll set into the `ExampleEapi` object complex properties to demonstrate the conversion into a simple structure.
|
169
|
-
|
170
|
-
```ruby
|
171
|
-
class ComplexValue
|
172
|
-
def to_h
|
173
|
-
{
|
174
|
-
a: Set.new(['hello', 'world', MyTestObject.new])
|
175
|
-
}
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
|
-
class ExampleEapi
|
180
|
-
include Eapi::Item
|
181
|
-
|
182
|
-
property :something, required: true
|
183
|
-
property :other
|
184
|
-
end
|
185
|
-
|
186
|
-
# TESTING `render`
|
187
|
-
|
188
|
-
list = Set.new [
|
189
|
-
OpenStruct.new(a: 1, 'b' => 2),
|
190
|
-
{c: 3, 'd' => 4},
|
191
|
-
nil
|
192
|
-
]
|
193
|
-
|
194
|
-
eapi = ExampleEapi.new something: list, other: ComplexValue.new
|
195
|
-
|
196
|
-
# same as eapi.to_h
|
197
|
-
eapi.render # =>
|
198
|
-
# {
|
199
|
-
# something: [
|
200
|
-
# {a: 1, b: 2},
|
201
|
-
# {c: 3, d: 4},
|
202
|
-
# ],
|
203
|
-
#
|
204
|
-
# other: {
|
205
|
-
# a: [
|
206
|
-
# 'hello',
|
207
|
-
# 'world',
|
208
|
-
# {a: 'hello'}
|
209
|
-
# ]
|
210
|
-
# }
|
211
|
-
# }
|
212
|
-
```
|
213
|
-
|
214
339
|
### Property definition
|
215
340
|
|
216
341
|
When defining the property, we can specify some options to specify what values are expected in that property. This serves for validation and automatic initialisation.
|
@@ -621,103 +746,6 @@ l.add(1)
|
|
621
746
|
l.valid? # => false
|
622
747
|
```
|
623
748
|
|
624
|
-
## Common to `Item` and `List`
|
625
|
-
|
626
|
-
The following features are shared between `List`s and `Item`s.
|
627
|
-
|
628
|
-
### Pose as other types
|
629
|
-
|
630
|
-
An Eapi class can poses as other types, for purposes of `type` checking in a property definition. We use the class method `is` for this.
|
631
|
-
|
632
|
-
the `is?` method is also available as an instance method.
|
633
|
-
|
634
|
-
Eapi also creates specific instance and class methods like `is_a_some_type?` or `is_an_another_type?`.
|
635
|
-
|
636
|
-
example:
|
637
|
-
|
638
|
-
```ruby
|
639
|
-
class SuperTestKlass
|
640
|
-
include Eapi::Item
|
641
|
-
end
|
642
|
-
|
643
|
-
class TestKlass < SuperTestKlass
|
644
|
-
is :one_thing, :other_thing, OtherType
|
645
|
-
end
|
646
|
-
|
647
|
-
TestKlass.is? TestKlass # => true
|
648
|
-
TestKlass.is? 'TestKlass' # => true
|
649
|
-
TestKlass.is? :TestKlass # => true
|
650
|
-
|
651
|
-
TestKlass.is? SuperTestKlass # => true
|
652
|
-
TestKlass.is? 'SuperTestKlass' # => true
|
653
|
-
TestKlass.is? :SuperTestKlass # => true
|
654
|
-
|
655
|
-
TestKlass.is? :one_thing # => true
|
656
|
-
TestKlass.is? :other_thing # => true
|
657
|
-
TestKlass.is? :other_thing # => true
|
658
|
-
TestKlass.is? OtherType # => true
|
659
|
-
TestKlass.is? :OtherType # => true
|
660
|
-
|
661
|
-
TestKlass.is? SomethingElse # => false
|
662
|
-
TestKlass.is? :SomethingElse # => false
|
663
|
-
|
664
|
-
# also works on instance
|
665
|
-
obj = TestKlass.new
|
666
|
-
obj.is? TestKlass # => true
|
667
|
-
obj.is? :one_thing # => true
|
668
|
-
|
669
|
-
# specific type test methods
|
670
|
-
TestKlass.is_a_test_klass? # => true
|
671
|
-
TestKlass.is_an_one_thing? # => true
|
672
|
-
TestKlass.is_a_super_duper_thing? # => false
|
673
|
-
|
674
|
-
obj.is_a_test_klass? # => true
|
675
|
-
obj.is_an_one_thing? # => true
|
676
|
-
obj.is_a_super_duper_thing? # => false
|
677
|
-
```
|
678
|
-
|
679
|
-
### Object creation shortcut: calling methods in Eapi
|
680
|
-
|
681
|
-
Calling a method with the desired class name in `Eapi` module will do the same as `DesiredClass.new(...)`. The name can be the same as the class, or an underscorised version, or a simple underscored one.
|
682
|
-
|
683
|
-
The goal is to use `Eapi.esr_search(name: 'Paco')` as a shortcut to `Esr::Search.new(name: 'Paco')`. We can also use `Eapi.Esr_Search(...)` and other combinations.
|
684
|
-
|
685
|
-
To show this feature and all the combinations for method names, we'll use the 2 example classes that are used in the actual test rspec.
|
686
|
-
|
687
|
-
```ruby
|
688
|
-
class MyTestKlassOutside
|
689
|
-
include Eapi::Item
|
690
|
-
|
691
|
-
property :something
|
692
|
-
end
|
693
|
-
|
694
|
-
module Somewhere
|
695
|
-
class TestKlassInModule
|
696
|
-
include Eapi::Item
|
697
|
-
|
698
|
-
property :something
|
699
|
-
end
|
700
|
-
end
|
701
|
-
```
|
702
|
-
|
703
|
-
As shown by rspec run:
|
704
|
-
|
705
|
-
```
|
706
|
-
initialise using method calls to Eapi
|
707
|
-
Eapi.MyTestKlassOutside(...)
|
708
|
-
calls MyTestKlassOutside.new
|
709
|
-
Eapi.my_test_klass_outside(...)
|
710
|
-
calls MyTestKlassOutside.new
|
711
|
-
Eapi.Somewhere__TestKlassInModule(...)
|
712
|
-
calls Somewhere::TestKlassInModule.new
|
713
|
-
Eapi.somewhere__test_klass_in_module(...)
|
714
|
-
calls Somewhere::TestKlassInModule.new
|
715
|
-
Eapi.Somewhere_TestKlassInModule(...)
|
716
|
-
calls Somewhere::TestKlassInModule.new
|
717
|
-
Eapi.somewhere_test_klass_in_module(...)
|
718
|
-
calls Somewhere::TestKlassInModule.new
|
719
|
-
```
|
720
|
-
|
721
749
|
## Using Eapi in your own library
|
722
750
|
|
723
751
|
You can add the functionality of Eapi to your own library module, and use it instead of `Eapi::Item` or `Eapi::List`.
|
data/lib/eapi.rb
CHANGED
data/lib/eapi/common.rb
CHANGED
data/lib/eapi/item.rb
CHANGED
@@ -12,20 +12,22 @@ module Eapi
|
|
12
12
|
Eapi::Common.add_features klass
|
13
13
|
end
|
14
14
|
|
15
|
-
def
|
16
|
-
|
17
|
-
create_hash
|
15
|
+
def to_h
|
16
|
+
render
|
18
17
|
end
|
19
18
|
|
20
|
-
|
21
|
-
|
22
|
-
def create_hash
|
19
|
+
def perform_render
|
23
20
|
{}.tap do |hash|
|
24
21
|
_properties.each do |prop|
|
25
22
|
val = converted_value_for(prop)
|
26
|
-
hash[prop] = val unless val
|
23
|
+
hash[prop] = val unless to_be_ignored?(val, prop)
|
27
24
|
end
|
28
25
|
end
|
29
26
|
end
|
27
|
+
|
28
|
+
private
|
29
|
+
def to_be_ignored?(value, property)
|
30
|
+
Eapi::ValueIgnoreChecker.to_be_ignored? value, self.class.ignore_definition(property)
|
31
|
+
end
|
30
32
|
end
|
31
33
|
end
|
data/lib/eapi/list.rb
CHANGED
@@ -30,15 +30,12 @@ module Eapi
|
|
30
30
|
true
|
31
31
|
end
|
32
32
|
|
33
|
-
def
|
34
|
-
|
35
|
-
create_array
|
33
|
+
def to_a
|
34
|
+
render
|
36
35
|
end
|
37
36
|
|
38
|
-
|
39
|
-
|
40
|
-
def create_array
|
41
|
-
_list.map { |val| convert_value val }
|
37
|
+
def perform_render
|
38
|
+
_list.map { |val| convert_value val }.reject { |x| to_be_ignored x }
|
42
39
|
end
|
43
40
|
|
44
41
|
def _list
|
@@ -77,6 +74,11 @@ module Eapi
|
|
77
74
|
|
78
75
|
protected :initialize_copy
|
79
76
|
|
77
|
+
private
|
78
|
+
def to_be_ignored(value)
|
79
|
+
Eapi::ValueIgnoreChecker.to_be_ignored? value, self.class.elements_ignore_definition
|
80
|
+
end
|
81
|
+
|
80
82
|
# transpose, assoc, rassoc , permutation, combination, repeated_permutation, repeated_combination, product, pack ?? => do not use the methods
|
81
83
|
end
|
82
84
|
|
@@ -10,7 +10,12 @@ module Eapi
|
|
10
10
|
|
11
11
|
define_method fluent_adder do |value|
|
12
12
|
current = send(getter) || send(init)
|
13
|
-
current
|
13
|
+
if current.respond_to? :add
|
14
|
+
current.add value
|
15
|
+
else
|
16
|
+
current << value
|
17
|
+
end
|
18
|
+
|
14
19
|
send(fluent_setter, current)
|
15
20
|
end
|
16
21
|
end
|
@@ -71,6 +71,10 @@ module Eapi
|
|
71
71
|
@_property_definitions ||= {}
|
72
72
|
end
|
73
73
|
|
74
|
+
def ignore_definition(field)
|
75
|
+
definition_for(field).fetch(:ignore, :nil?)
|
76
|
+
end
|
77
|
+
|
74
78
|
private :_property_allow_raw
|
75
79
|
private :_property_definitions
|
76
80
|
private :run_property_definition
|
@@ -90,13 +94,17 @@ module Eapi
|
|
90
94
|
property_allow_raw?(:_list)
|
91
95
|
end
|
92
96
|
|
97
|
+
def elements_ignore_definition
|
98
|
+
definition_for_elements.fetch(:ignore, :nil?)
|
99
|
+
end
|
100
|
+
|
93
101
|
def elements(definition)
|
94
102
|
run_list_definition definition
|
95
103
|
store_list_definition definition
|
96
104
|
end
|
97
105
|
|
98
106
|
def definition_for_elements
|
99
|
-
@_list_definition
|
107
|
+
@_list_definition ||= {}
|
100
108
|
end
|
101
109
|
|
102
110
|
def store_list_definition(definition)
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Eapi
|
2
|
+
class ValueIgnoreChecker
|
3
|
+
def self.to_be_ignored?(value, ignore_definition = nil)
|
4
|
+
if ignore_definition.nil?
|
5
|
+
check_by_default value
|
6
|
+
elsif !ignore_definition
|
7
|
+
false
|
8
|
+
elsif ignore_definition.respond_to? :call
|
9
|
+
check_by_callable value, ignore_definition
|
10
|
+
else
|
11
|
+
check_by_message value, ignore_definition
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
def self.check_by_default(value)
|
17
|
+
value.nil?
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.check_by_message(value, ignore_definition)
|
21
|
+
value.send ignore_definition
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.check_by_callable(value, ignore_definition)
|
25
|
+
ignore_definition.call value
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/eapi/version.rb
CHANGED
data/spec/ignore_spec.rb
ADDED
@@ -0,0 +1,178 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Eapi do
|
4
|
+
|
5
|
+
class IgnoreSpecTestItemDefault
|
6
|
+
include Eapi::Item
|
7
|
+
property :something
|
8
|
+
end
|
9
|
+
|
10
|
+
class IgnoreSpecTestItemFalse
|
11
|
+
include Eapi::Item
|
12
|
+
property :something, ignore: false
|
13
|
+
end
|
14
|
+
|
15
|
+
class IgnoreSpecTestItemSymbol
|
16
|
+
include Eapi::Item
|
17
|
+
property :something, ignore: :blank?
|
18
|
+
end
|
19
|
+
|
20
|
+
class IgnoreSpecTestItemProc
|
21
|
+
include Eapi::Item
|
22
|
+
property :something, ignore: Proc.new { |x| x.to_s == 'ignoreme' }
|
23
|
+
end
|
24
|
+
|
25
|
+
class IgnoreSpecTestListDefault
|
26
|
+
include Eapi::List
|
27
|
+
end
|
28
|
+
|
29
|
+
class IgnoreSpecTestListFalse
|
30
|
+
include Eapi::List
|
31
|
+
|
32
|
+
elements ignore: false
|
33
|
+
end
|
34
|
+
|
35
|
+
class IgnoreSpecTestListSymbol
|
36
|
+
include Eapi::List
|
37
|
+
|
38
|
+
elements ignore: :blank?
|
39
|
+
end
|
40
|
+
|
41
|
+
class IgnoreSpecTestListProc
|
42
|
+
include Eapi::List
|
43
|
+
|
44
|
+
elements ignore: Proc.new { |x| x.to_s == 'ignoreme' }
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
describe 'ignore values on render' do
|
49
|
+
describe 'default (no specification in definition)' do
|
50
|
+
describe 'Item' do
|
51
|
+
subject { IgnoreSpecTestItemDefault.new }
|
52
|
+
it 'ignore nil values' do
|
53
|
+
subject.something nil
|
54
|
+
expect_not_in_hash
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'does not ignore any other value' do
|
58
|
+
subject.something 1
|
59
|
+
expect_in_hash
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe 'List' do
|
64
|
+
subject { IgnoreSpecTestListDefault.new }
|
65
|
+
it 'ignore nil values' do
|
66
|
+
subject.add nil
|
67
|
+
expect_not_in_array
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'does not ignore any other value' do
|
71
|
+
subject.add 1
|
72
|
+
expect_in_array
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe 'message (symbol or string)' do
|
78
|
+
describe 'Item' do
|
79
|
+
subject { IgnoreSpecTestItemSymbol.new }
|
80
|
+
it 'ignore if sending the message to the value returns truthy' do
|
81
|
+
subject.something ""
|
82
|
+
expect_not_in_hash
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'does not ignore any other value' do
|
86
|
+
subject.something 1
|
87
|
+
expect_in_hash
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe 'List' do
|
92
|
+
subject { IgnoreSpecTestListSymbol.new }
|
93
|
+
it 'ignore if sending the message to the value returns truthy' do
|
94
|
+
subject.add ""
|
95
|
+
expect_not_in_array
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'does not ignore any other value' do
|
99
|
+
subject.add 1
|
100
|
+
expect_in_array
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe 'false' do
|
106
|
+
describe 'Item' do
|
107
|
+
subject { IgnoreSpecTestItemFalse.new }
|
108
|
+
it 'do not ignore any value (even nils)' do
|
109
|
+
subject.something nil
|
110
|
+
expect_in_hash
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'does not ignore any other value' do
|
114
|
+
subject.something 1
|
115
|
+
expect_in_hash
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe 'List' do
|
120
|
+
subject { IgnoreSpecTestListFalse.new }
|
121
|
+
it 'do not ignore any value (even nils)' do
|
122
|
+
subject.add nil
|
123
|
+
expect_in_array
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'does not ignore any other value' do
|
127
|
+
subject.add 1
|
128
|
+
expect_in_array
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe 'callable' do
|
134
|
+
describe 'Item' do
|
135
|
+
subject { IgnoreSpecTestItemProc.new }
|
136
|
+
it 'ignore if the callable element with the value returns truthy' do
|
137
|
+
subject.something :ignoreme
|
138
|
+
expect_not_in_hash
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'does not ignore any other value' do
|
142
|
+
subject.something 1
|
143
|
+
expect_in_hash
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
describe 'List' do
|
148
|
+
subject { IgnoreSpecTestListProc.new }
|
149
|
+
it 'ignore if the callable element with the value returns truthy' do
|
150
|
+
subject.add :ignoreme
|
151
|
+
expect_not_in_array
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'does not ignore any other value' do
|
155
|
+
subject.add 1
|
156
|
+
expect_in_array
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
|
163
|
+
def expect_not_in_hash
|
164
|
+
expect(subject.render.key? :something).to be false
|
165
|
+
end
|
166
|
+
|
167
|
+
def expect_in_hash
|
168
|
+
expect(subject.render.key? :something).to be true
|
169
|
+
end
|
170
|
+
|
171
|
+
def expect_not_in_array
|
172
|
+
expect(subject.render).to be_empty
|
173
|
+
end
|
174
|
+
|
175
|
+
def expect_in_array
|
176
|
+
expect(subject.render).not_to be_empty
|
177
|
+
end
|
178
|
+
end
|
@@ -8,6 +8,7 @@ RSpec.describe Eapi do
|
|
8
8
|
|
9
9
|
property :something, required: true
|
10
10
|
property :other
|
11
|
+
property :again
|
11
12
|
end
|
12
13
|
|
13
14
|
class MyTestObject
|
@@ -36,6 +37,24 @@ RSpec.describe Eapi do
|
|
36
37
|
end
|
37
38
|
end
|
38
39
|
|
40
|
+
class MyTestObjectComplexRender
|
41
|
+
def render
|
42
|
+
{
|
43
|
+
a: Set.new(['hello', 'world', MyTestObject.new])
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
def expected
|
48
|
+
{
|
49
|
+
a: [
|
50
|
+
'hello',
|
51
|
+
'world',
|
52
|
+
{a: 'hello'}
|
53
|
+
]
|
54
|
+
}
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
39
58
|
it 'raise error if invalid' do
|
40
59
|
eapi = MyTestClassToH.new
|
41
60
|
expect { eapi.to_h }.to raise_error do |error|
|
@@ -58,7 +77,7 @@ RSpec.describe Eapi do
|
|
58
77
|
expect(eapi.to_h).to eq expected
|
59
78
|
end
|
60
79
|
|
61
|
-
it 'hash with elements, all converted to basic Arrays and Hashes (keys as symbols), and
|
80
|
+
it 'hash with elements, all converted to basic Arrays and Hashes (keys as symbols), and excluding nils (if all validations pass)' do
|
62
81
|
list = Set.new [
|
63
82
|
OpenStruct.new(a: 1, 'b' => 2),
|
64
83
|
{c: 3, 'd' => 4},
|
@@ -66,6 +85,7 @@ RSpec.describe Eapi do
|
|
66
85
|
]
|
67
86
|
|
68
87
|
other = MyTestObjectComplex.new
|
88
|
+
again = MyTestObjectComplexRender.new
|
69
89
|
|
70
90
|
expected = {
|
71
91
|
something: [
|
@@ -73,12 +93,14 @@ RSpec.describe Eapi do
|
|
73
93
|
{c: 3, d: 4},
|
74
94
|
],
|
75
95
|
|
76
|
-
other: other.expected
|
96
|
+
other: other.expected,
|
97
|
+
again: again.expected
|
77
98
|
}
|
78
99
|
|
79
100
|
eapi = MyTestClassToH.new
|
80
101
|
eapi.something list
|
81
102
|
eapi.other other
|
103
|
+
eapi.again other
|
82
104
|
|
83
105
|
expect(eapi.to_h).to eq expected
|
84
106
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: eapi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eduardo Turiño
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-07-
|
11
|
+
date: 2014-07-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -211,15 +211,17 @@ files:
|
|
211
211
|
- lib/eapi/multiple_value.rb
|
212
212
|
- lib/eapi/type_checker.rb
|
213
213
|
- lib/eapi/value_converter.rb
|
214
|
+
- lib/eapi/value_ignore_checker.rb
|
214
215
|
- lib/eapi/version.rb
|
215
216
|
- spec/basic_spec.rb
|
216
217
|
- spec/definition_spec.rb
|
217
218
|
- spec/extension_spec.rb
|
218
219
|
- spec/function_spec.rb
|
220
|
+
- spec/ignore_spec.rb
|
219
221
|
- spec/list_elements_spec.rb
|
220
222
|
- spec/list_spec.rb
|
223
|
+
- spec/render_spec.rb
|
221
224
|
- spec/spec_helper.rb
|
222
|
-
- spec/to_h_spec.rb
|
223
225
|
- spec/type_spec.rb
|
224
226
|
- spec/validations_spec.rb
|
225
227
|
homepage: ''
|
@@ -252,10 +254,11 @@ test_files:
|
|
252
254
|
- spec/definition_spec.rb
|
253
255
|
- spec/extension_spec.rb
|
254
256
|
- spec/function_spec.rb
|
257
|
+
- spec/ignore_spec.rb
|
255
258
|
- spec/list_elements_spec.rb
|
256
259
|
- spec/list_spec.rb
|
260
|
+
- spec/render_spec.rb
|
257
261
|
- spec/spec_helper.rb
|
258
|
-
- spec/to_h_spec.rb
|
259
262
|
- spec/type_spec.rb
|
260
263
|
- spec/validations_spec.rb
|
261
264
|
has_rdoc:
|