darthjee-core_ext 1.2.6
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 +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
|