transproc 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|