monolens 0.6.2 → 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/coerce/array.rb +13 -0
- data/lib/monolens/stdlib/coerce.rb +6 -0
- 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/coerce/test_array.rb +13 -0
- data/spec/monolens/stdlib/core/test_digs.rb +87 -0
- data/spec/monolens/stdlib/object/test_select.rb +74 -0
- metadata +8 -3
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
|
@@ -22,6 +22,11 @@ module Monolens
|
|
22
22
|
end
|
23
23
|
module_function :string
|
24
24
|
|
25
|
+
def array(options, registry)
|
26
|
+
Array.new(options, registry)
|
27
|
+
end
|
28
|
+
module_function :array
|
29
|
+
|
25
30
|
Monolens.define_namespace 'coerce', self
|
26
31
|
end
|
27
32
|
end
|
@@ -29,3 +34,4 @@ require_relative 'coerce/date'
|
|
29
34
|
require_relative 'coerce/date_time'
|
30
35
|
require_relative 'coerce/integer'
|
31
36
|
require_relative 'coerce/string'
|
37
|
+
require_relative 'coerce/array'
|
@@ -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,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Monolens, 'coerce.array' do
|
4
|
+
subject do
|
5
|
+
Monolens.lens('coerce.array')
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'works' do
|
9
|
+
expect(subject.call(12)).to eql([12])
|
10
|
+
expect(subject.call(nil)).to eql([])
|
11
|
+
expect(subject.call([12, 13])).to eql([12, 13])
|
12
|
+
end
|
13
|
+
end
|
@@ -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:
|
11
|
+
date: 2024-07-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -130,6 +130,7 @@ files:
|
|
130
130
|
- lib/monolens/stdlib/check.rb
|
131
131
|
- lib/monolens/stdlib/check/not_empty.rb
|
132
132
|
- lib/monolens/stdlib/coerce.rb
|
133
|
+
- lib/monolens/stdlib/coerce/array.rb
|
133
134
|
- lib/monolens/stdlib/coerce/date.rb
|
134
135
|
- lib/monolens/stdlib/coerce/date_time.rb
|
135
136
|
- lib/monolens/stdlib/coerce/integer.rb
|
@@ -137,6 +138,7 @@ files:
|
|
137
138
|
- lib/monolens/stdlib/core.rb
|
138
139
|
- lib/monolens/stdlib/core/chain.rb
|
139
140
|
- lib/monolens/stdlib/core/dig.rb
|
141
|
+
- lib/monolens/stdlib/core/digs.rb
|
140
142
|
- lib/monolens/stdlib/core/literal.rb
|
141
143
|
- lib/monolens/stdlib/core/mapping.rb
|
142
144
|
- lib/monolens/stdlib/object.rb
|
@@ -152,6 +154,7 @@ files:
|
|
152
154
|
- lib/monolens/stdlib/skip/null.rb
|
153
155
|
- lib/monolens/stdlib/str.rb
|
154
156
|
- lib/monolens/stdlib/str/downcase.rb
|
157
|
+
- lib/monolens/stdlib/str/null_if_empty.rb
|
155
158
|
- lib/monolens/stdlib/str/split.rb
|
156
159
|
- lib/monolens/stdlib/str/strip.rb
|
157
160
|
- lib/monolens/stdlib/str/upcase.rb
|
@@ -193,11 +196,13 @@ files:
|
|
193
196
|
- spec/monolens/stdlib/array/test_join.rb
|
194
197
|
- spec/monolens/stdlib/array/test_map.rb
|
195
198
|
- spec/monolens/stdlib/check/test_not_empty.rb
|
199
|
+
- spec/monolens/stdlib/coerce/test_array.rb
|
196
200
|
- spec/monolens/stdlib/coerce/test_date.rb
|
197
201
|
- spec/monolens/stdlib/coerce/test_datetime.rb
|
198
202
|
- spec/monolens/stdlib/coerce/test_integer.rb
|
199
203
|
- spec/monolens/stdlib/coerce/test_string.rb
|
200
204
|
- spec/monolens/stdlib/core/test_dig.rb
|
205
|
+
- spec/monolens/stdlib/core/test_digs.rb
|
201
206
|
- spec/monolens/stdlib/core/test_literal.rb
|
202
207
|
- spec/monolens/stdlib/core/test_mapping.rb
|
203
208
|
- spec/monolens/stdlib/object/test_allbut.rb
|
@@ -242,7 +247,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
242
247
|
- !ruby/object:Gem::Version
|
243
248
|
version: '0'
|
244
249
|
requirements: []
|
245
|
-
rubygems_version: 3.
|
250
|
+
rubygems_version: 3.3.27
|
246
251
|
signing_key:
|
247
252
|
specification_version: 4
|
248
253
|
summary: Data transformations inspired by Cambria lenses
|