transproc 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/.rubocop.yml +66 -0
- data/.rubocop_todo.yml +11 -0
- data/.travis.yml +2 -1
- data/CHANGELOG.md +31 -2
- data/Gemfile +5 -0
- data/Guardfile +2 -2
- data/README.md +5 -4
- data/Rakefile +1 -1
- data/lib/transproc.rb +13 -2
- data/lib/transproc/all.rb +2 -0
- data/lib/transproc/array.rb +78 -1
- data/lib/transproc/class.rb +52 -0
- data/lib/transproc/composite.rb +50 -0
- data/lib/transproc/conditional.rb +0 -1
- data/lib/transproc/error.rb +16 -0
- data/lib/transproc/function.rb +8 -50
- data/lib/transproc/hash.rb +52 -2
- data/lib/transproc/object.rb +19 -0
- data/lib/transproc/version.rb +1 -1
- data/rakelib/mutant.rake +16 -0
- data/rakelib/rubocop.rake +18 -0
- data/spec/spec_helper.rb +4 -2
- data/spec/unit/array_transformations_spec.rb +166 -0
- data/spec/unit/class_transformations_spec.rb +47 -0
- data/spec/{integration → unit}/coercions_spec.rb +10 -10
- data/spec/{integration → unit}/composer_spec.rb +0 -0
- data/spec/{integration → unit}/conditional_spec.rb +2 -2
- data/spec/{integration → unit}/function_spec.rb +30 -7
- data/spec/{integration/hash_spec.rb → unit/hash_transformations_spec.rb} +71 -23
- data/spec/{integration → unit}/recursion_spec.rb +6 -9
- data/spec/unit/transproc_spec.rb +64 -0
- data/transproc.gemspec +10 -10
- metadata +28 -19
- data/spec/integration/array_spec.rb +0 -98
- data/spec/integration/transproc_spec.rb +0 -37
@@ -1,25 +1,25 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
4
|
-
describe 'to_string' do
|
3
|
+
describe Transproc::Coercions do
|
4
|
+
describe '.to_string' do
|
5
5
|
it 'turns integer into a string' do
|
6
6
|
expect(t(:to_string)[1]).to eql('1')
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
|
-
describe 'to_symbol' do
|
10
|
+
describe '.to_symbol' do
|
11
11
|
it 'turns string into a symbol' do
|
12
12
|
expect(t(:to_symbol)['test']).to eql(:test)
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
describe 'to_integer' do
|
16
|
+
describe '.to_integer' do
|
17
17
|
it 'turns string into an integer' do
|
18
18
|
expect(t(:to_integer)['1']).to eql(1)
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
describe 'to_float' do
|
22
|
+
describe '.to_float' do
|
23
23
|
it 'turns string into a float' do
|
24
24
|
expect(t(:to_float)['1']).to eql(1.0)
|
25
25
|
end
|
@@ -29,7 +29,7 @@ describe 'Transproc / Coercions' do
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
describe 'to_decimal' do
|
32
|
+
describe '.to_decimal' do
|
33
33
|
it 'turns string into a decimal' do
|
34
34
|
expect(t(:to_decimal)['1.251']).to eql(BigDecimal('1.251'))
|
35
35
|
end
|
@@ -43,28 +43,28 @@ describe 'Transproc / Coercions' do
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
-
describe 'to_date' do
|
46
|
+
describe '.to_date' do
|
47
47
|
it 'turns string into a date' do
|
48
48
|
date = Date.new(1983, 11, 18)
|
49
49
|
expect(t(:to_date)['18th, November 1983']).to eql(date)
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
-
describe 'to_time' do
|
53
|
+
describe '.to_time' do
|
54
54
|
it 'turns string into a time object' do
|
55
55
|
time = Time.new(2012, 1, 23, 11, 7, 7)
|
56
56
|
expect(t(:to_time)['2012-01-23 11:07:07']).to eql(time)
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
|
-
describe 'to_datetime' do
|
60
|
+
describe '.to_datetime' do
|
61
61
|
it 'turns string into a date' do
|
62
62
|
datetime = DateTime.new(2012, 1, 23, 11, 7, 7)
|
63
63
|
expect(t(:to_datetime)['2012-01-23 11:07:07']).to eql(datetime)
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
67
|
-
describe 'to_boolean' do
|
67
|
+
describe '.to_boolean' do
|
68
68
|
subject(:coercer) { t(:to_boolean) }
|
69
69
|
|
70
70
|
Transproc::Coercions::TRUE_VALUES.each do |value|
|
File without changes
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
4
|
-
describe 'guard' do
|
3
|
+
describe Transproc::Conditional do
|
4
|
+
describe '.guard' do
|
5
5
|
let(:fn) { t(:guard, ->(value) { value.is_a?(::String) }, t(:to_integer)) }
|
6
6
|
|
7
7
|
context 'when predicate returns truthy value' do
|
@@ -1,8 +1,8 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
4
|
-
describe
|
5
|
-
it
|
3
|
+
describe 'Transproc::Function' do
|
4
|
+
describe '#>>' do
|
5
|
+
it 'composes named functions' do
|
6
6
|
f1 = t(:symbolize_keys)
|
7
7
|
f2 = t(:rename_keys, user_name: :name)
|
8
8
|
|
@@ -12,7 +12,7 @@ describe "Transproc::Function" do
|
|
12
12
|
[
|
13
13
|
:symbolize_keys, [],
|
14
14
|
[
|
15
|
-
:rename_keys, [
|
15
|
+
:rename_keys, [user_name: :name]
|
16
16
|
]
|
17
17
|
]
|
18
18
|
)
|
@@ -25,7 +25,7 @@ describe "Transproc::Function" do
|
|
25
25
|
[
|
26
26
|
:symbolize_keys, [],
|
27
27
|
[
|
28
|
-
:rename_keys, [
|
28
|
+
:rename_keys, [user_name: :name]
|
29
29
|
],
|
30
30
|
[
|
31
31
|
:nest, [:details, [:name]]
|
@@ -36,10 +36,10 @@ describe "Transproc::Function" do
|
|
36
36
|
expect(f4['user_name' => 'Jane']).to eql(details: { name: 'Jane' })
|
37
37
|
end
|
38
38
|
|
39
|
-
it
|
39
|
+
it 'composes anonymous functions' do
|
40
40
|
# TODO: Use Transproc -> (v) { v.to_s } after release of jruby-9k
|
41
41
|
f1 = Transproc proc { |v, m| v * m }, 2
|
42
|
-
f2 = Transproc proc
|
42
|
+
f2 = Transproc proc(&:to_s)
|
43
43
|
|
44
44
|
f3 = f1 >> f2
|
45
45
|
|
@@ -52,5 +52,28 @@ describe "Transproc::Function" do
|
|
52
52
|
]
|
53
53
|
)
|
54
54
|
end
|
55
|
+
|
56
|
+
it 'plays well with registered compositions' do
|
57
|
+
Transproc.register(:user_names, t(:symbolize_keys) + t(:rename_keys, user_name: :name))
|
58
|
+
f = t(:user_names)
|
59
|
+
|
60
|
+
expect(f['user_name' => 'Jane']).to eql(name: 'Jane')
|
61
|
+
expect(f.to_ast).to eql(
|
62
|
+
[
|
63
|
+
:symbolize_keys, [],
|
64
|
+
[
|
65
|
+
:rename_keys, [user_name: :name]
|
66
|
+
]
|
67
|
+
]
|
68
|
+
)
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'plays well with registered functions' do
|
72
|
+
Transproc.register(:to_s, t(:to_string))
|
73
|
+
f = t(:to_s)
|
74
|
+
|
75
|
+
expect(f[:ok]).to eql('ok')
|
76
|
+
expect(f.to_ast).to eql([:to_string, []])
|
77
|
+
end
|
55
78
|
end
|
56
79
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
4
|
-
describe 'map_keys' do
|
3
|
+
describe Transproc::HashTransformations do
|
4
|
+
describe '.map_keys' do
|
5
5
|
it 'returns a new hash with given proc applied to keys' do
|
6
6
|
map_keys = t(:map_keys, ->(key) { key.strip })
|
7
7
|
|
@@ -13,7 +13,7 @@ describe 'Hash mapping with Transproc' do
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
describe 'map_keys!' do
|
16
|
+
describe '.map_keys!' do
|
17
17
|
it 'returns updated hash with given proc applied to keys' do
|
18
18
|
map_keys = t(:map_keys!, ->(key) { key.strip })
|
19
19
|
|
@@ -25,7 +25,7 @@ describe 'Hash mapping with Transproc' do
|
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
-
describe 'symbolize_keys' do
|
28
|
+
describe '.symbolize_keys' do
|
29
29
|
it 'returns a new hash with symbolized keys' do
|
30
30
|
symbolize_keys = t(:symbolize_keys)
|
31
31
|
|
@@ -37,7 +37,7 @@ describe 'Hash mapping with Transproc' do
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
describe 'symbolize_keys!' do
|
40
|
+
describe '.symbolize_keys!' do
|
41
41
|
it 'returns updated hash with symbolized keys' do
|
42
42
|
symbolize_keys = t(:symbolize_keys!)
|
43
43
|
|
@@ -50,7 +50,7 @@ describe 'Hash mapping with Transproc' do
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
-
describe 'stringify_keys' do
|
53
|
+
describe '.stringify_keys' do
|
54
54
|
it 'returns a new hash with stringified keys' do
|
55
55
|
stringify_keys = t(:stringify_keys)
|
56
56
|
|
@@ -62,7 +62,7 @@ describe 'Hash mapping with Transproc' do
|
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
-
describe 'stringify_keys!' do
|
65
|
+
describe '.stringify_keys!' do
|
66
66
|
it 'returns a new hash with stringified keys' do
|
67
67
|
stringify_keys = t(:stringify_keys!)
|
68
68
|
|
@@ -74,7 +74,7 @@ describe 'Hash mapping with Transproc' do
|
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
-
describe 'map_values' do
|
77
|
+
describe '.map_values' do
|
78
78
|
it 'returns a new hash with given proc applied to values' do
|
79
79
|
map_values = t(:map_values, ->(value) { value.strip })
|
80
80
|
|
@@ -86,7 +86,7 @@ describe 'Hash mapping with Transproc' do
|
|
86
86
|
end
|
87
87
|
end
|
88
88
|
|
89
|
-
describe 'map_values!' do
|
89
|
+
describe '.map_values!' do
|
90
90
|
it 'returns updated hash with given proc applied to values' do
|
91
91
|
map_values = t(:map_values!, ->(value) { value.strip })
|
92
92
|
|
@@ -98,7 +98,7 @@ describe 'Hash mapping with Transproc' do
|
|
98
98
|
end
|
99
99
|
end
|
100
100
|
|
101
|
-
describe 'rename_keys' do
|
101
|
+
describe '.rename_keys' do
|
102
102
|
it 'returns a new hash with applied functions' do
|
103
103
|
map = t(:rename_keys, 'foo' => :foo)
|
104
104
|
|
@@ -110,7 +110,7 @@ describe 'Hash mapping with Transproc' do
|
|
110
110
|
end
|
111
111
|
end
|
112
112
|
|
113
|
-
describe 'rename_keys!' do
|
113
|
+
describe '.rename_keys!' do
|
114
114
|
it 'returns updated hash with applied functions' do
|
115
115
|
map = t(:rename_keys!, 'foo' => :foo)
|
116
116
|
|
@@ -123,7 +123,7 @@ describe 'Hash mapping with Transproc' do
|
|
123
123
|
end
|
124
124
|
end
|
125
125
|
|
126
|
-
describe 'map_value' do
|
126
|
+
describe '.map_value' do
|
127
127
|
it 'applies function to value under specified key' do
|
128
128
|
transformation = t(:map_value, :user, t(:symbolize_keys))
|
129
129
|
|
@@ -135,7 +135,7 @@ describe 'Hash mapping with Transproc' do
|
|
135
135
|
end
|
136
136
|
end
|
137
137
|
|
138
|
-
describe 'map_value!' do
|
138
|
+
describe '.map_value!' do
|
139
139
|
it 'applies function to value under specified key' do
|
140
140
|
transformation = t(:map_value!, :user, t(:symbolize_keys))
|
141
141
|
|
@@ -148,7 +148,7 @@ describe 'Hash mapping with Transproc' do
|
|
148
148
|
end
|
149
149
|
end
|
150
150
|
|
151
|
-
describe 'nest' do
|
151
|
+
describe '.nest' do
|
152
152
|
it 'returns new hash with keys nested under a new key' do
|
153
153
|
nest = t(:nest, :baz, ['foo'])
|
154
154
|
|
@@ -160,7 +160,7 @@ describe 'Hash mapping with Transproc' do
|
|
160
160
|
end
|
161
161
|
end
|
162
162
|
|
163
|
-
describe 'nest!' do
|
163
|
+
describe '.nest!' do
|
164
164
|
it 'returns new hash with keys nested under a new key' do
|
165
165
|
nest = t(:nest!, :baz, ['one', 'two', 'not-here'])
|
166
166
|
|
@@ -184,12 +184,12 @@ describe 'Hash mapping with Transproc' do
|
|
184
184
|
end
|
185
185
|
end
|
186
186
|
|
187
|
-
describe 'unwrap!' do
|
187
|
+
describe '.unwrap!' do
|
188
188
|
it 'returns updated hash with nested keys lifted to the root' do
|
189
|
-
unwrap = t(:unwrap!, 'wrapped',
|
189
|
+
unwrap = t(:unwrap!, 'wrapped', %w(one))
|
190
190
|
|
191
191
|
input = { 'foo' => 'bar', 'wrapped' => { 'one' => nil, 'two' => false } }
|
192
|
-
output = { 'foo' => 'bar', 'one' => nil, 'two' => false }
|
192
|
+
output = { 'foo' => 'bar', 'one' => nil, 'wrapped' => { 'two' => false } }
|
193
193
|
|
194
194
|
unwrap[input]
|
195
195
|
|
@@ -208,18 +208,20 @@ describe 'Hash mapping with Transproc' do
|
|
208
208
|
end
|
209
209
|
end
|
210
210
|
|
211
|
-
describe 'unwrap' do
|
211
|
+
describe '.unwrap' do
|
212
212
|
it 'returns new hash with nested keys lifted to the root' do
|
213
|
-
unwrap = t(:unwrap, 'wrapped'
|
213
|
+
unwrap = t(:unwrap, 'wrapped')
|
214
214
|
|
215
215
|
input = {
|
216
216
|
'foo' => 'bar',
|
217
217
|
'wrapped' => { 'one' => nil, 'two' => false }
|
218
218
|
}.freeze
|
219
219
|
|
220
|
-
expect(unwrap[input]).to eql(
|
221
|
-
|
222
|
-
|
220
|
+
expect(unwrap[input]).to eql(
|
221
|
+
'foo' => 'bar',
|
222
|
+
'one' => nil,
|
223
|
+
'two' => false
|
224
|
+
)
|
223
225
|
end
|
224
226
|
end
|
225
227
|
|
@@ -252,4 +254,50 @@ describe 'Hash mapping with Transproc' do
|
|
252
254
|
expect(result).to eql(output)
|
253
255
|
end
|
254
256
|
end
|
257
|
+
|
258
|
+
describe '.reject_keys!' do
|
259
|
+
it 'returns an updated hash with rejected keys' do
|
260
|
+
reject_keys = t(:reject_keys, [:name, :age])
|
261
|
+
|
262
|
+
input = { name: 'Jane', email: 'jane@doe.org', age: 21 }
|
263
|
+
output = { email: 'jane@doe.org' }
|
264
|
+
|
265
|
+
expect(reject_keys[input]).to eql(output)
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
describe '.reject_keys' do
|
270
|
+
it 'returns a new hash with rejected keys' do
|
271
|
+
reject_keys = t(:reject_keys, [:name, :age])
|
272
|
+
|
273
|
+
input = { name: 'Jane', email: 'jane@doe.org', age: 21 }
|
274
|
+
output = { email: 'jane@doe.org' }
|
275
|
+
|
276
|
+
expect(reject_keys[input]).to eql(output)
|
277
|
+
expect(input).to eql(name: 'Jane', email: 'jane@doe.org', age: 21)
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
describe '.accept_keys!' do
|
282
|
+
it 'returns an updated hash with accepted keys' do
|
283
|
+
accept_keys = t(:accept_keys, [:age])
|
284
|
+
|
285
|
+
input = { name: 'Jane', email: 'jane@doe.org', age: 21 }
|
286
|
+
output = { age: 21 }
|
287
|
+
|
288
|
+
expect(accept_keys[input]).to eql(output)
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
describe '.reject_keys' do
|
293
|
+
it 'returns a new hash with rejected keys' do
|
294
|
+
accept_keys = t(:accept_keys, [:age])
|
295
|
+
|
296
|
+
input = { name: 'Jane', email: 'jane@doe.org', age: 21 }
|
297
|
+
output = { age: 21 }
|
298
|
+
|
299
|
+
expect(accept_keys[input]).to eql(output)
|
300
|
+
expect(input).to eql(name: 'Jane', email: 'jane@doe.org', age: 21)
|
301
|
+
end
|
302
|
+
end
|
255
303
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
4
|
-
describe 'array_recursion' do
|
3
|
+
describe Transproc::Recursion do
|
4
|
+
describe '.array_recursion' do
|
5
5
|
let(:original) do
|
6
6
|
[
|
7
7
|
'foo',
|
@@ -29,16 +29,13 @@ describe 'Recursive transformations with Transproc' do
|
|
29
29
|
[
|
30
30
|
'foo',
|
31
31
|
'bar',
|
32
|
-
|
33
|
-
'foo',
|
34
|
-
'bar'
|
35
|
-
]
|
32
|
+
%w(foo bar)
|
36
33
|
]
|
37
34
|
]
|
38
35
|
end
|
39
36
|
|
40
37
|
context 'when function is non-destructive' do
|
41
|
-
let(:map) { t(:array_recursion, proc
|
38
|
+
let(:map) { t(:array_recursion, proc(&:compact)) }
|
42
39
|
|
43
40
|
it 'applies funtions to all items recursively' do
|
44
41
|
expect(map[input]).to eql(output)
|
@@ -47,7 +44,7 @@ describe 'Recursive transformations with Transproc' do
|
|
47
44
|
end
|
48
45
|
|
49
46
|
context 'when function is destructive' do
|
50
|
-
let(:map) { t(:array_recursion, proc
|
47
|
+
let(:map) { t(:array_recursion, proc(&:compact!)) }
|
51
48
|
|
52
49
|
it 'applies funtions to all items recursively and destructively' do
|
53
50
|
expect(map[input]).to eql(output)
|
@@ -56,7 +53,7 @@ describe 'Recursive transformations with Transproc' do
|
|
56
53
|
end
|
57
54
|
end
|
58
55
|
|
59
|
-
describe 'hash_recursion' do
|
56
|
+
describe '.hash_recursion' do
|
60
57
|
let(:original) do
|
61
58
|
{
|
62
59
|
'foo' => 'bar',
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Transproc do
|
4
|
+
describe 'composition' do
|
5
|
+
it 'allows composing two transformation functions' do
|
6
|
+
input = '1'
|
7
|
+
output = 1.0
|
8
|
+
|
9
|
+
to_i = t(-> value { value.to_i })
|
10
|
+
to_f = t(-> value { value.to_f })
|
11
|
+
|
12
|
+
result = to_i >> to_f
|
13
|
+
|
14
|
+
expect(result[input]).to eql(output)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '.register' do
|
19
|
+
it 'allows registering functions by name' do
|
20
|
+
Transproc.register(:identity, -> value { value })
|
21
|
+
|
22
|
+
value = 'hello world'
|
23
|
+
|
24
|
+
result = t(:identity)[value]
|
25
|
+
|
26
|
+
expect(result).to be(value)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'allows registering function by passing a block' do
|
30
|
+
Transproc.register(:to_boolean1) { |value| value == 'true' }
|
31
|
+
|
32
|
+
result = t(-> value { value.to_s }) >> t(:to_boolean1)
|
33
|
+
|
34
|
+
expect(result[:true]).to be(true)
|
35
|
+
expect(result[:false]).to be(false)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'raises a Transproc::FunctionAlreadyRegisteredError if a function is already registered' do
|
39
|
+
Transproc.register(:bogus) {}
|
40
|
+
expect { Transproc.register(:bogus) {} }.to raise_error(Transproc::FunctionAlreadyRegisteredError)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe 'nonextistent functions' do
|
45
|
+
it 'raises a Transproc::FunctionNotFoundError if asking for function that is non exsistent' do
|
46
|
+
expect {
|
47
|
+
Transproc(:i_do_not_exist)
|
48
|
+
raise('expected the :i_do_not_exist function to not exist')
|
49
|
+
}.to raise_error(Transproc::FunctionNotFoundError)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe 'handling malformed input' do
|
54
|
+
it 'raises a Transproc::MalformedInputError' do
|
55
|
+
Transproc.register(:im_dangerous, ->(){
|
56
|
+
raise ArgumentError.new('sorry, you got some bad apples in your input')
|
57
|
+
})
|
58
|
+
|
59
|
+
expect{
|
60
|
+
Transproc(:im_dangerous)[hello: 'world']
|
61
|
+
}.to raise_error(Transproc::MalformedInputError)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|