monolens 0.6.3 → 0.6.4
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/lib/monolens/stdlib/core/digs.rb +63 -0
- data/lib/monolens/stdlib/core.rb +6 -0
- data/lib/monolens/stdlib/object/select.rb +10 -2
- data/lib/monolens/stdlib/str/null_if_empty.rb +15 -0
- data/lib/monolens/stdlib/str.rb +6 -0
- data/lib/monolens/version.rb +1 -1
- data/spec/monolens/stdlib/core/test_digs.rb +87 -0
- data/spec/monolens/stdlib/object/test_select.rb +74 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 808d9126b39444b34dde2d81926a680af37ad5351994e6b640a035b3555807fb
|
4
|
+
data.tar.gz: f2eab3c0f2911e83096e7a72520d9812575830c38192ad98b0f609b68f6ab814
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 50586006606bd32d8f1cf2d35c885c906883d61da10a7746f63ca7cf1e66e6fd81624025def49287400edee1554e86c69e7f27573bc8ad9311872be8a545270a
|
7
|
+
data.tar.gz: acdb391077a3c35b1888fb2cb6f8bbddf8be6d5ba68001f6297a0686079fc5b1aa13077eca3079fa8d98c4d56d804da43ca0ccb5c912b579117f815d312a673f
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Monolens
|
2
|
+
module Core
|
3
|
+
class Digs
|
4
|
+
include Lens
|
5
|
+
|
6
|
+
signature(Type::Diggable, Type::Any, {
|
7
|
+
defn: [
|
8
|
+
Type::Array.of(Type::Array.of(Type::Any.of(Type::Integer, Type::String))),
|
9
|
+
true
|
10
|
+
],
|
11
|
+
on_missing: [Type::Strategy.missing(%w{fail null}), false]
|
12
|
+
})
|
13
|
+
|
14
|
+
def call(arg, world = {})
|
15
|
+
to_dig = option(:defn, [])
|
16
|
+
to_dig.map {|digging|
|
17
|
+
digging.inject(arg) do |memo, part|
|
18
|
+
dig_on(part, memo, world)
|
19
|
+
end
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def path
|
26
|
+
option(:defn, []).join('.')
|
27
|
+
end
|
28
|
+
|
29
|
+
def dig_on(attr, arg, world)
|
30
|
+
if arg.is_a?(::Array)
|
31
|
+
index = attr.to_i
|
32
|
+
on_missing(world) if index >= arg.size
|
33
|
+
arg[index]
|
34
|
+
elsif arg.is_a?(::Hash)
|
35
|
+
actual, value = fetch_on(attr, arg)
|
36
|
+
on_missing(world) unless actual
|
37
|
+
value
|
38
|
+
elsif arg
|
39
|
+
if attr.is_a?(::Integer)
|
40
|
+
is_array!(arg, world)
|
41
|
+
else
|
42
|
+
is_hash!(arg, world)
|
43
|
+
end
|
44
|
+
else
|
45
|
+
on_missing(world)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def on_missing(world)
|
50
|
+
strategy = option(:on_missing, :fail)
|
51
|
+
case strategy.to_sym
|
52
|
+
when :fail
|
53
|
+
fail!("Unable to find #{path}", world)
|
54
|
+
when :null
|
55
|
+
nil
|
56
|
+
else
|
57
|
+
raise Monolens::Error, "Unexpected missing strategy `#{strategy}`"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
private :on_missing
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/monolens/stdlib/core.rb
CHANGED
@@ -12,6 +12,11 @@ module Monolens
|
|
12
12
|
end
|
13
13
|
module_function :dig
|
14
14
|
|
15
|
+
def digs(options, registry)
|
16
|
+
Digs.new(options, registry)
|
17
|
+
end
|
18
|
+
module_function :digs
|
19
|
+
|
15
20
|
def literal(options, registry)
|
16
21
|
Literal.new(options, registry)
|
17
22
|
end
|
@@ -27,5 +32,6 @@ module Monolens
|
|
27
32
|
end
|
28
33
|
require_relative 'core/chain'
|
29
34
|
require_relative 'core/dig'
|
35
|
+
require_relative 'core/digs'
|
30
36
|
require_relative 'core/mapping'
|
31
37
|
require_relative 'core/literal'
|
@@ -4,7 +4,8 @@ module Monolens
|
|
4
4
|
include Lens
|
5
5
|
|
6
6
|
signature(Type::Object, Type::Object, {
|
7
|
-
strategy: [Type::Strategy.selection(%w{all first}), false],
|
7
|
+
strategy: [Type::Strategy.selection(%w{all first concat}), false],
|
8
|
+
separator: [Type::String, false],
|
8
9
|
defn: [Type::Any.of(
|
9
10
|
Type::Array.of(Type::Name),
|
10
11
|
Type::Map.of(Type::Name, Type::Any.of(Type::Array.of(Type::Name), Type::Name))
|
@@ -41,13 +42,20 @@ module Monolens
|
|
41
42
|
end
|
42
43
|
|
43
44
|
def do_array_select(arg, selector, world)
|
44
|
-
case option(:strategy, :all).to_sym
|
45
|
+
case strategy = option(:strategy, :all).to_sym
|
45
46
|
when :all
|
46
47
|
selector.each_with_object([]) do |old_attr, values|
|
47
48
|
catch (:skip) do
|
48
49
|
values << do_single_select(arg, old_attr, world)
|
49
50
|
end
|
50
51
|
end
|
52
|
+
when :concat
|
53
|
+
values = selector.each_with_object([]) do |old_attr, values|
|
54
|
+
catch (:skip) do
|
55
|
+
values << do_single_select(arg, old_attr, world)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
values.join(option(:separator, ' '))
|
51
59
|
when :first
|
52
60
|
selector.each do |old_attr|
|
53
61
|
actual, fetched = fetch_on(old_attr, arg)
|
data/lib/monolens/stdlib/str.rb
CHANGED
@@ -7,6 +7,11 @@ module Monolens
|
|
7
7
|
end
|
8
8
|
module_function :downcase
|
9
9
|
|
10
|
+
def nullIfEmpty(options, registry)
|
11
|
+
NullIfEmpty.new(options, registry)
|
12
|
+
end
|
13
|
+
module_function :nullIfEmpty
|
14
|
+
|
10
15
|
def strip(options, registry)
|
11
16
|
Strip.new(options, registry)
|
12
17
|
end
|
@@ -29,3 +34,4 @@ require_relative 'str/downcase'
|
|
29
34
|
require_relative 'str/strip'
|
30
35
|
require_relative 'str/split'
|
31
36
|
require_relative 'str/upcase'
|
37
|
+
require_relative 'str/null_if_empty'
|
data/lib/monolens/version.rb
CHANGED
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Monolens, "core.digs" do
|
4
|
+
let(:lens) do
|
5
|
+
Monolens.lens('core.digs' => {
|
6
|
+
defn: [
|
7
|
+
['foo'],
|
8
|
+
['hobbies', 1, 'name'],
|
9
|
+
]
|
10
|
+
})
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'works' do
|
14
|
+
input = {
|
15
|
+
hobbies: [
|
16
|
+
{ name: 'programming' },
|
17
|
+
{ name: 'music' }
|
18
|
+
],
|
19
|
+
foo: 'Hello'
|
20
|
+
}
|
21
|
+
expected = ['Hello', 'music']
|
22
|
+
expect(lens.call(input)).to eql(expected)
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'error handling' do
|
26
|
+
let(:lens) do
|
27
|
+
Monolens.lens({
|
28
|
+
'array.map' => {
|
29
|
+
lenses: {
|
30
|
+
'core.digs' => {
|
31
|
+
on_missing: on_missing,
|
32
|
+
defn: [
|
33
|
+
['foo'],
|
34
|
+
['hobbies', 1, 'name'],
|
35
|
+
]
|
36
|
+
}.compact
|
37
|
+
}
|
38
|
+
}
|
39
|
+
})
|
40
|
+
end
|
41
|
+
|
42
|
+
subject do
|
43
|
+
begin
|
44
|
+
lens.call(input)
|
45
|
+
rescue Monolens::LensError => ex
|
46
|
+
ex
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'default behavior' do
|
51
|
+
let(:on_missing) do
|
52
|
+
nil
|
53
|
+
end
|
54
|
+
|
55
|
+
let(:input) do
|
56
|
+
[{
|
57
|
+
hobbies: [
|
58
|
+
{ name: 'programming' }
|
59
|
+
]
|
60
|
+
}]
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'fails as expected' do
|
64
|
+
expect(subject).to be_a(Monolens::LensError)
|
65
|
+
expect(subject.location).to eql([0])
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'on_missing: null' do
|
70
|
+
let(:on_missing) do
|
71
|
+
:null
|
72
|
+
end
|
73
|
+
|
74
|
+
let(:input) do
|
75
|
+
[{
|
76
|
+
hobbies: [
|
77
|
+
{ name: 'programming' }
|
78
|
+
]
|
79
|
+
}]
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'works' do
|
83
|
+
expect(subject).to eql([[nil, nil]])
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -160,6 +160,80 @@ describe Monolens, 'object.select' do
|
|
160
160
|
end
|
161
161
|
end
|
162
162
|
|
163
|
+
context 'when using strategy: concat' do
|
164
|
+
subject do
|
165
|
+
Monolens.lens('object.select' => {
|
166
|
+
defn: {
|
167
|
+
name: [:firstname, :lastname],
|
168
|
+
status: :priority
|
169
|
+
},
|
170
|
+
strategy: 'concat',
|
171
|
+
separator: "\n",
|
172
|
+
on_missing: on_missing
|
173
|
+
}.compact)
|
174
|
+
end
|
175
|
+
|
176
|
+
context 'with :skip as on_missing' do
|
177
|
+
let(:on_missing) do
|
178
|
+
:skip
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'works as expected with first only is present' do
|
182
|
+
input = {
|
183
|
+
firstname: 'Bernard',
|
184
|
+
priority: 12
|
185
|
+
}
|
186
|
+
expected = {
|
187
|
+
name: 'Bernard',
|
188
|
+
status: 12
|
189
|
+
}
|
190
|
+
expect(subject.call(input)).to eql(expected)
|
191
|
+
end
|
192
|
+
|
193
|
+
it 'works as expected when second only is present' do
|
194
|
+
input = {
|
195
|
+
lastname: 'Lambeau',
|
196
|
+
priority: 12
|
197
|
+
}
|
198
|
+
expected = {
|
199
|
+
name: 'Lambeau',
|
200
|
+
status: 12
|
201
|
+
}
|
202
|
+
expect(subject.call(input)).to eql(expected)
|
203
|
+
end
|
204
|
+
|
205
|
+
it 'works as expected when both are present' do
|
206
|
+
input = {
|
207
|
+
firstname: 'Bernard',
|
208
|
+
lastname: 'Lambeau',
|
209
|
+
priority: 12
|
210
|
+
}
|
211
|
+
expected = {
|
212
|
+
name: "Bernard\nLambeau",
|
213
|
+
status: 12
|
214
|
+
}
|
215
|
+
expect(subject.call(input)).to eql(expected)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
context 'with on_missing: null' do
|
220
|
+
let(:on_missing) do
|
221
|
+
:null
|
222
|
+
end
|
223
|
+
|
224
|
+
it 'works as expected when missing' do
|
225
|
+
input = {
|
226
|
+
priority: 12
|
227
|
+
}
|
228
|
+
expected = {
|
229
|
+
name: "\n",
|
230
|
+
status: 12
|
231
|
+
}
|
232
|
+
expect(subject.call(input)).to eql(expected)
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
163
237
|
context 'when using an array as selection' do
|
164
238
|
subject do
|
165
239
|
Monolens.lens('object.select' => {
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: monolens
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bernard Lambeau
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-07-
|
11
|
+
date: 2024-07-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -138,6 +138,7 @@ files:
|
|
138
138
|
- lib/monolens/stdlib/core.rb
|
139
139
|
- lib/monolens/stdlib/core/chain.rb
|
140
140
|
- lib/monolens/stdlib/core/dig.rb
|
141
|
+
- lib/monolens/stdlib/core/digs.rb
|
141
142
|
- lib/monolens/stdlib/core/literal.rb
|
142
143
|
- lib/monolens/stdlib/core/mapping.rb
|
143
144
|
- lib/monolens/stdlib/object.rb
|
@@ -153,6 +154,7 @@ files:
|
|
153
154
|
- lib/monolens/stdlib/skip/null.rb
|
154
155
|
- lib/monolens/stdlib/str.rb
|
155
156
|
- lib/monolens/stdlib/str/downcase.rb
|
157
|
+
- lib/monolens/stdlib/str/null_if_empty.rb
|
156
158
|
- lib/monolens/stdlib/str/split.rb
|
157
159
|
- lib/monolens/stdlib/str/strip.rb
|
158
160
|
- lib/monolens/stdlib/str/upcase.rb
|
@@ -200,6 +202,7 @@ files:
|
|
200
202
|
- spec/monolens/stdlib/coerce/test_integer.rb
|
201
203
|
- spec/monolens/stdlib/coerce/test_string.rb
|
202
204
|
- spec/monolens/stdlib/core/test_dig.rb
|
205
|
+
- spec/monolens/stdlib/core/test_digs.rb
|
203
206
|
- spec/monolens/stdlib/core/test_literal.rb
|
204
207
|
- spec/monolens/stdlib/core/test_mapping.rb
|
205
208
|
- spec/monolens/stdlib/object/test_allbut.rb
|