darthjee-core_ext 1.2.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/.rspec +1 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +62 -0
- data/LICENSE +22 -0
- data/README.md +188 -0
- data/Rakefile +7 -0
- data/core_ext.gemspec +27 -0
- data/lib/array.rb +23 -0
- data/lib/array/hash_builder.rb +20 -0
- data/lib/darthjee.rb +4 -0
- data/lib/darthjee/core_ext.rb +12 -0
- data/lib/darthjee/core_ext/version.rb +5 -0
- data/lib/enumerable.rb +45 -0
- data/lib/hash.rb +195 -0
- data/lib/hash/deep_hash_constructor.rb +83 -0
- data/lib/hash/key_changer.rb +76 -0
- data/lib/hash/value_changer.rb +61 -0
- data/lib/numeric.rb +6 -0
- data/lib/symbol.rb +9 -0
- data/spec/lib/array_spec.rb +229 -0
- data/spec/lib/enumerable_spec.rb +31 -0
- data/spec/lib/hash/deep_hash_constructor_spec.rb +167 -0
- data/spec/lib/hash/key_changer_spec.rb +55 -0
- data/spec/lib/hash_spec.rb +347 -0
- data/spec/lib/numeric_spec.rb +61 -0
- data/spec/lib/symbol_spec.rb +35 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/support/models/hash/value_changer/dummy.rb +15 -0
- data/spec/support/models/hash/value_changer/dummy_iteractor.rb +12 -0
- data/spec/support/shared_examples/array_random.rb +16 -0
- data/spec/support/shared_examples/chain_fetch.rb +88 -0
- data/spec/support/shared_examples/chain_hash_keys_changer.rb +88 -0
- data/spec/support/shared_examples/clean.rb +143 -0
- data/spec/support/shared_examples/expected.rb +6 -0
- data/spec/support/shared_examples/hash_keys_changer.rb +85 -0
- data/spec/support/shared_examples/keys_appender.rb +43 -0
- data/spec/support/shared_examples/keys_camelizer.rb +285 -0
- data/spec/support/shared_examples/keys_underscorer.rb +82 -0
- data/spec/support/shared_examples/remap.rb +89 -0
- data/spec/support/shared_examples/value_changer.rb +92 -0
- metadata +217 -0
@@ -0,0 +1,31 @@
|
|
1
|
+
describe Enumerable do
|
2
|
+
describe '#clean!' do
|
3
|
+
it_behaves_like 'an array clean method', :clean!
|
4
|
+
it_behaves_like 'a hash clean method', :clean!
|
5
|
+
|
6
|
+
it 'changes the original hash' do
|
7
|
+
hash = { a: nil}
|
8
|
+
expect { hash.clean! }.to change { hash }
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'changes original array' do
|
12
|
+
array = [{ a: nil}]
|
13
|
+
expect { array.clean! }.to change { array }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '#clean' do
|
18
|
+
it_behaves_like 'an array clean method', :clean
|
19
|
+
it_behaves_like 'a hash clean method', :clean
|
20
|
+
|
21
|
+
it 'does not change the original hash' do
|
22
|
+
hash = { a: nil}
|
23
|
+
expect { hash.clean }.not_to change { hash }
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'does not change the original array' do
|
27
|
+
array = [{ a: nil}]
|
28
|
+
expect { array.clean }.not_to change { array }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,167 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hash::DeepHashConstructor do
|
4
|
+
let(:subject) { described_class.new('.') }
|
5
|
+
let(:deep_hash) { subject.deep_hash(hash) }
|
6
|
+
|
7
|
+
describe '.deep_hash' do
|
8
|
+
let(:hash) do
|
9
|
+
{
|
10
|
+
'person.name' => 'Some name',
|
11
|
+
'person.age' => 22,
|
12
|
+
'status' => :success,
|
13
|
+
'vehicle.fuel' => 'GASOLINE',
|
14
|
+
'vehicle.doors' => 4
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
let(:expected) do
|
19
|
+
{
|
20
|
+
'person' => { 'name' => 'Some name', 'age' => 22 },
|
21
|
+
'vehicle' => { 'fuel' => 'GASOLINE', 'doors' => 4 },
|
22
|
+
'status' => :success
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'build a deep hash' do
|
27
|
+
expect(deep_hash).to eq(expected)
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'with indexed keys' do
|
31
|
+
let(:hash) do
|
32
|
+
{
|
33
|
+
'person[0].name' => 'First person',
|
34
|
+
'person[0].age' => 22,
|
35
|
+
'person[1].name' => 'Second person',
|
36
|
+
'person[1].age' => 27,
|
37
|
+
'device[0]' => 'GEAR_LOCK',
|
38
|
+
'device[1]' => 'GPS',
|
39
|
+
'zipCode' => '122345-123'
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
let(:expected) do
|
44
|
+
{
|
45
|
+
'person' => [
|
46
|
+
{ 'name' => 'First person', 'age' => 22 },
|
47
|
+
{ 'name' => 'Second person', 'age' => 27 }
|
48
|
+
],
|
49
|
+
'device' => %w(GEAR_LOCK GPS),
|
50
|
+
'zipCode' => '122345-123'
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'build a deep hash with arrays' do
|
55
|
+
expect(deep_hash).to eq(expected)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'with a n level hash' do
|
60
|
+
let(:hash) do
|
61
|
+
{
|
62
|
+
'quote_request.personal.person.name' => 'Some name',
|
63
|
+
'quote_request.personal.person.age' => 22,
|
64
|
+
'quote_request.insurance.vehicle.fuel' => 'GASOLINE',
|
65
|
+
'quote_request.insurance.vehicle.doors' => 4,
|
66
|
+
'request.status' => :success,
|
67
|
+
'trials' => 3
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
let(:expected) do
|
72
|
+
{
|
73
|
+
'quote_request' => {
|
74
|
+
'personal' => {
|
75
|
+
'person' => { 'name' => 'Some name', 'age' => 22 }
|
76
|
+
},
|
77
|
+
'insurance' => {
|
78
|
+
'vehicle' => { 'fuel' => 'GASOLINE', 'doors' => 4 }
|
79
|
+
}
|
80
|
+
},
|
81
|
+
'request' => { 'status' => :success },
|
82
|
+
'trials' => 3
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'build a deep hash with arrays' do
|
87
|
+
expect(deep_hash).to eq(expected)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context 'with a n level hash and arrays' do
|
92
|
+
let(:hash) do
|
93
|
+
{
|
94
|
+
'quote_request.personal.person[0].name' => 'Some name 1',
|
95
|
+
'quote_request.personal.person[0].age' => 22,
|
96
|
+
'quote_request.personal.person[1].name' => 'Some name 2',
|
97
|
+
'quote_request.personal.person[1].age' => 23,
|
98
|
+
'request[0].status.clazz' => String,
|
99
|
+
'request[1].status.clazz' => Integer,
|
100
|
+
'request[2].status.clazz' => Date,
|
101
|
+
'trials' => 3
|
102
|
+
}
|
103
|
+
end
|
104
|
+
|
105
|
+
let(:expected) do
|
106
|
+
{
|
107
|
+
'quote_request' => {
|
108
|
+
'personal' => {
|
109
|
+
'person' => [
|
110
|
+
{ 'name' => 'Some name 1', 'age' => 22 },
|
111
|
+
{ 'name' => 'Some name 2', 'age' => 23 }
|
112
|
+
]
|
113
|
+
}
|
114
|
+
},
|
115
|
+
'request' => [
|
116
|
+
{ 'status' => { 'clazz' => String } },
|
117
|
+
{ 'status' => { 'clazz' => Integer } },
|
118
|
+
{ 'status' => { 'clazz' => Date } }
|
119
|
+
],
|
120
|
+
'trials' => 3
|
121
|
+
}
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'build a deep hash with arrays' do
|
125
|
+
expect(deep_hash).to eq(expected)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context 'with custom separator' do
|
130
|
+
let(:subject) { described_class.new('_') }
|
131
|
+
let(:hash) do
|
132
|
+
{
|
133
|
+
'person_name' => 'Some name',
|
134
|
+
'person_age' => 22,
|
135
|
+
'status' => :success,
|
136
|
+
'vehicle_fuel' => 'GASOLINE',
|
137
|
+
'vehicle_doors' => 4
|
138
|
+
}
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'build a deep hash with arrays' do
|
142
|
+
expect(deep_hash).to eq(expected)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
context 'with custom separator on n level deep hash' do
|
147
|
+
let(:subject) { described_class.new('_') }
|
148
|
+
let(:hash) do
|
149
|
+
{
|
150
|
+
'person_name_clazz' => String
|
151
|
+
}
|
152
|
+
end
|
153
|
+
|
154
|
+
let(:expected) do
|
155
|
+
{
|
156
|
+
'person' => {
|
157
|
+
'name' => { 'clazz' => String }
|
158
|
+
}
|
159
|
+
}
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'build a deep hash with arrays' do
|
163
|
+
expect(deep_hash).to eq(expected)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hash::KeyChanger do
|
4
|
+
let(:subject) { described_class.new(hash) }
|
5
|
+
|
6
|
+
describe '#underscore_keys' do
|
7
|
+
let(:hash) { { keyUnderscore: 1 } }
|
8
|
+
|
9
|
+
it 'underscore all the keys' do
|
10
|
+
expect(subject.underscore_keys).to eq(key_underscore: 1)
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'when hash is a many level hash' do
|
14
|
+
let(:hash) { { keyUnderscore: { anotherKey: 1 } } }
|
15
|
+
|
16
|
+
it 'underscore all the keys' do
|
17
|
+
expect(subject.underscore_keys).to eq(key_underscore: { another_key: 1 })
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'when hash has an array' do
|
22
|
+
let(:hash) { { keyUnderscore: [{ anotherKey: 1 }] } }
|
23
|
+
|
24
|
+
it 'underscore all the keys' do
|
25
|
+
expect(subject.underscore_keys).to eq(key_underscore: [{ another_key: 1 }])
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'changes the hash' do
|
30
|
+
it 'underscore all the keys' do
|
31
|
+
expect do
|
32
|
+
subject.underscore_keys
|
33
|
+
end.to change { hash }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'when giving non recursive options' do
|
38
|
+
context 'when hash is a many level hash' do
|
39
|
+
let(:hash) { { keyUnderscore: { anotherKey: 1 } } }
|
40
|
+
|
41
|
+
it 'underscore all the keys' do
|
42
|
+
expect(subject.underscore_keys(recursive: false)).to eq(key_underscore: { anotherKey: 1 })
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'when hash has an array' do
|
47
|
+
let(:hash) { { keyUnderscore: [{ anotherKey: 1 }] } }
|
48
|
+
|
49
|
+
it 'underscore all the keys' do
|
50
|
+
expect(subject.underscore_keys(recursive: false)).to eq(key_underscore: [{ anotherKey: 1 }])
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,347 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hash do
|
4
|
+
it_behaves_like 'a class with change_key method'
|
5
|
+
it_behaves_like 'a class with chain_change_key method'
|
6
|
+
it_behaves_like 'a class with camlize_keys method'
|
7
|
+
it_behaves_like 'a class with underscore_keys method'
|
8
|
+
it_behaves_like 'a class with append_keys method'
|
9
|
+
it_behaves_like 'a class with change_values method'
|
10
|
+
it_behaves_like 'a class with remap method'
|
11
|
+
it_behaves_like 'an object with chain_fetch method'
|
12
|
+
|
13
|
+
describe :squash do
|
14
|
+
let(:hash) { { a: { b: 1, c: { d: 2 } } } }
|
15
|
+
|
16
|
+
it 'flattens the hash' do
|
17
|
+
expect(hash.squash).to eq('a.b' => 1, 'a.c.d' => 2)
|
18
|
+
end
|
19
|
+
|
20
|
+
it { expect { hash.squash }.not_to change { hash } }
|
21
|
+
|
22
|
+
context 'with array value' do
|
23
|
+
let(:hash) { { a: { b: [1, { x: 3, y: { z: 4 } }] } } }
|
24
|
+
|
25
|
+
it 'flattens the hash' do
|
26
|
+
expect(hash.squash).to eq('a.b' => [1, { x: 3, y: { z: 4 } }])
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe :sort_keys do
|
32
|
+
it 'sorts keys as symbols' do
|
33
|
+
expect({ b: 1, a: 2 }.sort_keys).to eq(a: 2, b: 1)
|
34
|
+
end
|
35
|
+
it 'sorts keys as string' do
|
36
|
+
expect({ 'b' => 1, 'a' => 2 }.sort_keys).to eq('a' => 2, 'b' => 1)
|
37
|
+
end
|
38
|
+
it 'sorts keys recursively' do
|
39
|
+
expect({ b: 1, a: { d: 3, c: 4 } }.sort_keys).to eq(a: { c: 4, d: 3 }, b: 1)
|
40
|
+
end
|
41
|
+
it 'sorts keys recursively when argumen is passed' do
|
42
|
+
expect({ b: 1, a: { d: 3, c: 4 } }.sort_keys(recursive: true)).to eq(a: { c: 4, d: 3 }, b: 1)
|
43
|
+
end
|
44
|
+
it 'does not sorts keys recursively when argumen is passed' do
|
45
|
+
expect({ b: 1, a: { d: 3, c: 4 } }.sort_keys(recursive: false)).to eq(a: { d: 3, c: 4 }, b: 1)
|
46
|
+
end
|
47
|
+
it 'sort recursevely on many levels' do
|
48
|
+
hash = { b: 1, a: { d: 2, c: { e: 3, f: 4 } } }
|
49
|
+
expected = { a: { c: { f: 4, e: 3 }, d: 2 }, b: 1 }
|
50
|
+
expect(hash.sort_keys(recursive: true)).to eq(expected)
|
51
|
+
end
|
52
|
+
it 'applies to arrays as well' do
|
53
|
+
hash = { b: 1, a: { d: 2, c: [{ e: 3, f: 4 }] } }
|
54
|
+
expected = { a: { c: [{ f: 4, e: 3 }], d: 2 }, b: 1 }
|
55
|
+
expect(hash.sort_keys(recursive: true)).to eq(expected)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe :exclusive_merge do
|
60
|
+
let(:subject) { { a: 1, b: 2 } }
|
61
|
+
let(:other) { { b: 3, c: 4 } }
|
62
|
+
|
63
|
+
it 'merge only the common keys' do
|
64
|
+
expect(subject.exclusive_merge(other)).to eq(a: 1, b: 3)
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'does not change the original hash' do
|
68
|
+
expect { subject.exclusive_merge(other) }.not_to change { subject }
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe :exclusive_merge! do
|
73
|
+
let(:subject) { { a: 1, b: 2 } }
|
74
|
+
let(:other) { { b: 3, c: 4 } }
|
75
|
+
|
76
|
+
it 'merge only the common keys' do
|
77
|
+
expect(subject.exclusive_merge!(other)).to eq(a: 1, b: 3)
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'does not change the original hash' do
|
81
|
+
expect { subject.exclusive_merge!(other) }.to change { subject }
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe :to_deep_hash do
|
86
|
+
let(:subject) do
|
87
|
+
{
|
88
|
+
'person.name' => 'Some name',
|
89
|
+
'person.age' => 22,
|
90
|
+
'status' => :success,
|
91
|
+
'vehicle.fuel' => 'GASOLINE',
|
92
|
+
'vehicle.doors' => 4
|
93
|
+
}
|
94
|
+
end
|
95
|
+
|
96
|
+
let(:expected) do
|
97
|
+
{
|
98
|
+
'person' => { 'name' => 'Some name', 'age' => 22 },
|
99
|
+
'vehicle' => { 'fuel' => 'GASOLINE', 'doors' => 4 },
|
100
|
+
'status' => :success
|
101
|
+
}
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'build a deep hash' do
|
105
|
+
expect(subject.to_deep_hash).to eq(expected)
|
106
|
+
end
|
107
|
+
|
108
|
+
context 'with indexed keys' do
|
109
|
+
let(:subject) do
|
110
|
+
{
|
111
|
+
'person[0].name' => 'First person',
|
112
|
+
'person[0].age' => 22,
|
113
|
+
'person[1].name' => 'Second person',
|
114
|
+
'person[1].age' => 27,
|
115
|
+
'device[0]' => 'GEAR_LOCK',
|
116
|
+
'device[1]' => 'GPS',
|
117
|
+
'zipCode' => '122345-123'
|
118
|
+
}
|
119
|
+
end
|
120
|
+
|
121
|
+
let(:expected) do
|
122
|
+
{
|
123
|
+
'person' => [
|
124
|
+
{ 'name' => 'First person', 'age' => 22 },
|
125
|
+
{ 'name' => 'Second person', 'age' => 27 }
|
126
|
+
],
|
127
|
+
'device' => %w(GEAR_LOCK GPS),
|
128
|
+
'zipCode' => '122345-123'
|
129
|
+
}
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'build a deep hash with arrays' do
|
133
|
+
expect(subject.to_deep_hash).to eq(expected)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
context 'with a n level hash' do
|
138
|
+
let(:subject) do
|
139
|
+
{
|
140
|
+
'quote_request.personal.person.name' => 'Some name',
|
141
|
+
'quote_request.personal.person.age' => 22,
|
142
|
+
'quote_request.insurance.vehicle.fuel' => 'GASOLINE',
|
143
|
+
'quote_request.insurance.vehicle.doors' => 4,
|
144
|
+
'request.status' => :success,
|
145
|
+
'trials' => 3
|
146
|
+
}
|
147
|
+
end
|
148
|
+
|
149
|
+
let(:expected) do
|
150
|
+
{
|
151
|
+
'quote_request' => {
|
152
|
+
'personal' => {
|
153
|
+
'person' => { 'name' => 'Some name', 'age' => 22 }
|
154
|
+
},
|
155
|
+
'insurance' => {
|
156
|
+
'vehicle' => { 'fuel' => 'GASOLINE', 'doors' => 4 }
|
157
|
+
}
|
158
|
+
},
|
159
|
+
'request' => { 'status' => :success },
|
160
|
+
'trials' => 3
|
161
|
+
}
|
162
|
+
end
|
163
|
+
|
164
|
+
it 'build a deep hash with arrays' do
|
165
|
+
expect(subject.to_deep_hash).to eq(expected)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
context 'with a n level hash and arrays' do
|
170
|
+
let(:subject) do
|
171
|
+
{
|
172
|
+
'quote_request.personal.person[0].name' => 'Some name 1',
|
173
|
+
'quote_request.personal.person[0].age' => 22,
|
174
|
+
'quote_request.personal.person[1].name' => 'Some name 2',
|
175
|
+
'quote_request.personal.person[1].age' => 23,
|
176
|
+
'request[0].status.clazz' => String,
|
177
|
+
'request[1].status.clazz' => Integer,
|
178
|
+
'request[2].status.clazz' => Date,
|
179
|
+
'trials' => 3
|
180
|
+
}
|
181
|
+
end
|
182
|
+
|
183
|
+
let(:expected) do
|
184
|
+
{
|
185
|
+
'quote_request' => {
|
186
|
+
'personal' => {
|
187
|
+
'person' => [
|
188
|
+
{ 'name' => 'Some name 1', 'age' => 22 },
|
189
|
+
{ 'name' => 'Some name 2', 'age' => 23 }
|
190
|
+
]
|
191
|
+
}
|
192
|
+
},
|
193
|
+
'request' => [
|
194
|
+
{ 'status' => { 'clazz' => String } },
|
195
|
+
{ 'status' => { 'clazz' => Integer } },
|
196
|
+
{ 'status' => { 'clazz' => Date } }
|
197
|
+
],
|
198
|
+
'trials' => 3
|
199
|
+
}
|
200
|
+
end
|
201
|
+
|
202
|
+
it 'build a deep hash with arrays' do
|
203
|
+
expect(subject.to_deep_hash).to eq(expected)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
context 'with custom separator' do
|
208
|
+
let(:subject) do
|
209
|
+
{
|
210
|
+
'person_name' => 'Some name',
|
211
|
+
'person_age' => 22,
|
212
|
+
'status' => :success,
|
213
|
+
'vehicle_fuel' => 'GASOLINE',
|
214
|
+
'vehicle_doors' => 4
|
215
|
+
}
|
216
|
+
end
|
217
|
+
|
218
|
+
it 'build a deep hash with arrays' do
|
219
|
+
expect(subject.to_deep_hash('_')).to eq(expected)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
context 'with custom separator on n level deep hash' do
|
224
|
+
let(:subject) do
|
225
|
+
{
|
226
|
+
'person_name_clazz' => String
|
227
|
+
}
|
228
|
+
end
|
229
|
+
|
230
|
+
let(:expected) do
|
231
|
+
{
|
232
|
+
'person' => {
|
233
|
+
'name' => { 'clazz' => String }
|
234
|
+
}
|
235
|
+
}
|
236
|
+
end
|
237
|
+
|
238
|
+
it 'build a deep hash with arrays' do
|
239
|
+
expect(subject.to_deep_hash('_')).to eq(expected)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
describe '#map_and_find' do
|
245
|
+
let(:hash) { { a: 1, b: 2, c: 3, d: 4 } }
|
246
|
+
let(:value) { hash.map_and_find(&block) }
|
247
|
+
|
248
|
+
context 'when block returns nil' do
|
249
|
+
let(:block) { proc {} }
|
250
|
+
it { expect(value).to be_nil }
|
251
|
+
end
|
252
|
+
|
253
|
+
context 'when block returns false' do
|
254
|
+
let(:block) { proc { false } }
|
255
|
+
it { expect(value).to be_nil }
|
256
|
+
end
|
257
|
+
|
258
|
+
context 'when block returns a true evaluated value' do
|
259
|
+
let(:block) { proc { |_, v| v.to_s } }
|
260
|
+
|
261
|
+
it { expect(value).to eq('1') }
|
262
|
+
|
263
|
+
context 'when block returns the key and not the value' do
|
264
|
+
let(:block) { proc { |k, v| v > 1 && k } }
|
265
|
+
|
266
|
+
it { expect(value).to eq(:b) }
|
267
|
+
end
|
268
|
+
|
269
|
+
context 'but not for the first value' do
|
270
|
+
let(:transformer) { double(:transformer) }
|
271
|
+
let(:block) { proc { |_, v| transformer.transform(v) } }
|
272
|
+
|
273
|
+
before do
|
274
|
+
allow(transformer).to receive(:transform) do |v|
|
275
|
+
v.to_s if v > 1
|
276
|
+
end
|
277
|
+
value
|
278
|
+
end
|
279
|
+
|
280
|
+
it { expect(value).to eq('2') }
|
281
|
+
it 'calls the mapping only until it returns a valid value' do
|
282
|
+
expect(transformer).to have_received(:transform).exactly(2)
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
context 'when the block accepts one argument' do
|
288
|
+
let(:block) { proc { |v| v } }
|
289
|
+
|
290
|
+
it do
|
291
|
+
expect(value).to eq([:a, 1])
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
describe '#map_and_select' do
|
297
|
+
let(:hash) { { a: 1, b: 2, c: 3, d: 4 } }
|
298
|
+
let(:list) { hash.map_and_select(&block) }
|
299
|
+
|
300
|
+
context 'when block returns nil' do
|
301
|
+
let(:block) { proc {} }
|
302
|
+
it { expect(list).to be_empty }
|
303
|
+
end
|
304
|
+
|
305
|
+
context 'when block returns false' do
|
306
|
+
let(:block) { proc { false } }
|
307
|
+
it { expect(list).to be_empty }
|
308
|
+
end
|
309
|
+
|
310
|
+
context 'when block returns a true evaluated value' do
|
311
|
+
let(:block) { proc { |_, v| v.to_s } }
|
312
|
+
|
313
|
+
it { expect(list).to eq((1..4).map(&:to_s)) }
|
314
|
+
|
315
|
+
context 'when block returns the key and not the value' do
|
316
|
+
let(:block) { proc { |k, v| v > 1 && k } }
|
317
|
+
|
318
|
+
it { expect(list).to eq([:b, :c, :d]) }
|
319
|
+
end
|
320
|
+
|
321
|
+
context 'but not for the first value' do
|
322
|
+
let(:transformer) { double(:transformer) }
|
323
|
+
let(:block) { proc { |_, v| transformer.transform(v) } }
|
324
|
+
|
325
|
+
before do
|
326
|
+
allow(transformer).to receive(:transform) do |v|
|
327
|
+
v.to_s if v > 1
|
328
|
+
end
|
329
|
+
list
|
330
|
+
end
|
331
|
+
|
332
|
+
it { expect(list).to eq(hash.values[1..-1].map(&:to_s)) }
|
333
|
+
it 'calls the mapping only once for each value' do
|
334
|
+
expect(transformer).to have_received(:transform).exactly(4)
|
335
|
+
end
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
context 'when the block accepts one argument' do
|
340
|
+
let(:block) { proc { |v| v } }
|
341
|
+
|
342
|
+
it do
|
343
|
+
expect(list).to eq([[:a, 1], [:b, 2], [:c, 3], [:d, 4]])
|
344
|
+
end
|
345
|
+
end
|
346
|
+
end
|
347
|
+
end
|