darthjee-core_ext 1.5.6 → 1.6.0
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/.circleci/config.yml +14 -0
- data/.rubocop.yml +17 -0
- data/.rubocop_todo.yml +12 -0
- data/Gemfile +2 -1
- data/Rakefile +2 -0
- data/core_ext.gemspec +6 -3
- data/lib/darthjee/core_ext/array/hash_builder.rb +21 -13
- data/lib/darthjee/core_ext/array.rb +4 -2
- data/lib/darthjee/core_ext/date.rb +2 -0
- data/lib/darthjee/core_ext/enumerable.rb +5 -3
- data/lib/darthjee/core_ext/hash/chain_fetcher.rb +33 -0
- data/lib/darthjee/core_ext/hash/deep_hash_constructor.rb +62 -60
- data/lib/darthjee/core_ext/hash/key_changer.rb +64 -54
- data/lib/darthjee/core_ext/hash/keys_sorter.rb +31 -0
- data/lib/darthjee/core_ext/hash/squasher.rb +31 -0
- data/lib/darthjee/core_ext/hash/to_hash_mapper.rb +21 -0
- data/lib/darthjee/core_ext/hash/value_changer.rb +48 -44
- data/lib/darthjee/core_ext/hash.rb +28 -58
- data/lib/darthjee/core_ext/math.rb +4 -2
- data/lib/darthjee/core_ext/numeric.rb +5 -3
- data/lib/darthjee/core_ext/object/default_value.rb +2 -1
- data/lib/darthjee/core_ext/object.rb +2 -0
- data/lib/darthjee/core_ext/symbol.rb +2 -0
- data/lib/darthjee/core_ext/time.rb +2 -0
- data/lib/darthjee/core_ext/version.rb +3 -1
- data/lib/darthjee/core_ext.rb +2 -0
- data/lib/darthjee.rb +2 -1
- data/spec/lib/array_spec.rb +27 -19
- data/spec/lib/date_spec.rb +2 -0
- data/spec/lib/enumerable_spec.rb +10 -8
- data/spec/lib/hash/chain_fetcher_spec.rb +11 -0
- data/spec/lib/hash/deep_hash_constructor_spec.rb +3 -1
- data/spec/lib/hash/key_changer_spec.rb +19 -5
- data/spec/lib/hash/keys_sorter_spec.rb +10 -0
- data/spec/lib/hash/squasher_spec.rb +9 -0
- data/spec/lib/hash/to_hash_mapper_spec.rb +10 -0
- data/spec/lib/hash_spec.rb +16 -46
- data/spec/lib/math_spec.rb +2 -0
- data/spec/lib/numeric_spec.rb +2 -0
- data/spec/lib/object/default_value_spe.rb +2 -0
- data/spec/lib/object_spec.rb +2 -0
- data/spec/lib/symbol_spec.rb +2 -0
- data/spec/lib/time_spec.rb +2 -0
- data/spec/spec_helper.rb +2 -1
- data/spec/support/models/default_value.rb +2 -0
- data/spec/support/models/hash/value_changer/dummy.rb +19 -13
- data/spec/support/models/hash/value_changer/dummy_iteractor.rb +13 -8
- data/spec/support/shared_examples/{array_random.rb → array/array_random.rb} +5 -2
- data/spec/support/shared_examples/clean.rb +14 -2
- data/spec/support/shared_examples/date.rb +2 -0
- data/spec/support/shared_examples/expected.rb +2 -1
- data/spec/support/shared_examples/{chain_fetch.rb → hash/chain_fetch.rb} +9 -7
- data/spec/support/shared_examples/{chain_hash_keys_changer.rb → hash/chain_hash_keys_changer.rb} +14 -11
- data/spec/support/shared_examples/{hash_keys_changer.rb → hash/hash_keys_changer.rb} +7 -5
- data/spec/support/shared_examples/hash/hash_squasher.rb +23 -0
- data/spec/support/shared_examples/{hash_transpose.rb → hash/hash_transpose.rb} +8 -6
- data/spec/support/shared_examples/hash/keys_appender.rb +69 -0
- data/spec/support/shared_examples/{keys_camelizer.rb → hash/keys_camelizer.rb} +6 -4
- data/spec/support/shared_examples/hash/keys_sorter.rb +67 -0
- data/spec/support/shared_examples/{keys_underscorer.rb → hash/keys_underscorer.rb} +4 -3
- data/spec/support/shared_examples/{map_to_hash.rb → hash/map_to_hash.rb} +16 -16
- data/spec/support/shared_examples/{remap.rb → hash/remap.rb} +16 -13
- data/spec/support/shared_examples/hash/value_changer.rb +192 -0
- metadata +76 -30
- data/circle.yml +0 -10
- data/spec/support/shared_examples/keys_appender.rb +0 -43
- data/spec/support/shared_examples/value_changer.rb +0 -147
data/spec/lib/hash_spec.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
describe Hash do
|
@@ -8,54 +10,22 @@ describe Hash do
|
|
8
10
|
it_behaves_like 'a class with append_keys method'
|
9
11
|
it_behaves_like 'a class with change_values method'
|
10
12
|
it_behaves_like 'a class with remap method'
|
11
|
-
it_behaves_like 'an object with chain_fetch method'
|
12
|
-
it_behaves_like 'a hash with map_to_hash method'
|
13
13
|
it_behaves_like 'a class with transpose methods'
|
14
14
|
|
15
|
-
|
16
|
-
let(:
|
17
|
-
|
18
|
-
it 'flattens the hash' do
|
19
|
-
expect(hash.squash).to eq('a.b' => 1, 'a.c.d' => 2)
|
20
|
-
end
|
21
|
-
|
22
|
-
it { expect { hash.squash }.not_to change { hash } }
|
15
|
+
it_behaves_like 'an object with capable of performing chain fetch' do
|
16
|
+
let(:result) { hash.chain_fetch(*keys, &block) }
|
17
|
+
end
|
23
18
|
|
24
|
-
|
25
|
-
|
19
|
+
it_behaves_like 'a class that has a method to squash a hash' do
|
20
|
+
let(:squashed) { hash.squash }
|
21
|
+
end
|
26
22
|
|
27
|
-
|
28
|
-
|
29
|
-
end
|
30
|
-
end
|
23
|
+
it_behaves_like 'a hash with map_to_hash method' do
|
24
|
+
let(:mapped) { hash.map_to_hash(&mapping_block) }
|
31
25
|
end
|
32
26
|
|
33
|
-
|
34
|
-
|
35
|
-
expect({ b: 1, a: 2 }.sort_keys).to eq(a: 2, b: 1)
|
36
|
-
end
|
37
|
-
it 'sorts keys as string' do
|
38
|
-
expect({ 'b' => 1, 'a' => 2 }.sort_keys).to eq('a' => 2, 'b' => 1)
|
39
|
-
end
|
40
|
-
it 'sorts keys recursively' do
|
41
|
-
expect({ b: 1, a: { d: 3, c: 4 } }.sort_keys).to eq(a: { c: 4, d: 3 }, b: 1)
|
42
|
-
end
|
43
|
-
it 'sorts keys recursively when argumen is passed' do
|
44
|
-
expect({ b: 1, a: { d: 3, c: 4 } }.sort_keys(recursive: true)).to eq(a: { c: 4, d: 3 }, b: 1)
|
45
|
-
end
|
46
|
-
it 'does not sorts keys recursively when argumen is passed' do
|
47
|
-
expect({ b: 1, a: { d: 3, c: 4 } }.sort_keys(recursive: false)).to eq(a: { d: 3, c: 4 }, b: 1)
|
48
|
-
end
|
49
|
-
it 'sort recursevely on many levels' do
|
50
|
-
hash = { b: 1, a: { d: 2, c: { e: 3, f: 4 } } }
|
51
|
-
expected = { a: { c: { f: 4, e: 3 }, d: 2 }, b: 1 }
|
52
|
-
expect(hash.sort_keys(recursive: true)).to eq(expected)
|
53
|
-
end
|
54
|
-
it 'applies to arrays as well' do
|
55
|
-
hash = { b: 1, a: { d: 2, c: [{ e: 3, f: 4 }] } }
|
56
|
-
expected = { a: { c: [{ f: 4, e: 3 }], d: 2 }, b: 1 }
|
57
|
-
expect(hash.sort_keys(recursive: true)).to eq(expected)
|
58
|
-
end
|
27
|
+
it_behaves_like 'a class with a keys sort method' do
|
28
|
+
let(:result) { hash.sort_keys(**options) }
|
59
29
|
end
|
60
30
|
|
61
31
|
describe :exclusive_merge do
|
@@ -67,7 +37,7 @@ describe Hash do
|
|
67
37
|
end
|
68
38
|
|
69
39
|
it 'does not change the original hash' do
|
70
|
-
expect { subject.exclusive_merge(other) }.not_to
|
40
|
+
expect { subject.exclusive_merge(other) }.not_to(change { subject })
|
71
41
|
end
|
72
42
|
end
|
73
43
|
|
@@ -80,7 +50,7 @@ describe Hash do
|
|
80
50
|
end
|
81
51
|
|
82
52
|
it 'does not change the original hash' do
|
83
|
-
expect { subject.exclusive_merge!(other) }.to
|
53
|
+
expect { subject.exclusive_merge!(other) }.to(change { subject })
|
84
54
|
end
|
85
55
|
end
|
86
56
|
|
@@ -126,7 +96,7 @@ describe Hash do
|
|
126
96
|
{ 'name' => 'First person', 'age' => 22 },
|
127
97
|
{ 'name' => 'Second person', 'age' => 27 }
|
128
98
|
],
|
129
|
-
'device' => %w
|
99
|
+
'device' => %w[GEAR_LOCK GPS],
|
130
100
|
'zipCode' => '122345-123'
|
131
101
|
}
|
132
102
|
end
|
@@ -317,7 +287,7 @@ describe Hash do
|
|
317
287
|
context 'when block returns the key and not the value' do
|
318
288
|
let(:block) { proc { |k, v| v > 1 && k } }
|
319
289
|
|
320
|
-
it { expect(list).to eq([
|
290
|
+
it { expect(list).to eq(%i[b c d]) }
|
321
291
|
end
|
322
292
|
|
323
293
|
context 'but not for the first value' do
|
data/spec/lib/math_spec.rb
CHANGED
data/spec/lib/numeric_spec.rb
CHANGED
data/spec/lib/object_spec.rb
CHANGED
data/spec/lib/symbol_spec.rb
CHANGED
data/spec/lib/time_spec.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'simplecov'
|
2
4
|
|
3
5
|
SimpleCov.profiles.define 'gem' do
|
@@ -20,7 +22,6 @@ require 'darthjee/core_ext'
|
|
20
22
|
Dir['./spec/support/**/*.rb'].each { |f| require f }
|
21
23
|
|
22
24
|
RSpec.configure do |config|
|
23
|
-
config.treat_symbols_as_metadata_keys_with_true_values = true
|
24
25
|
config.run_all_when_everything_filtered = true
|
25
26
|
config.filter_run :focus
|
26
27
|
|
@@ -1,19 +1,25 @@
|
|
1
|
-
|
2
|
-
attr_reader :value
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
3
|
+
class Hash
|
4
|
+
class ValueChanger
|
5
|
+
class Dummy
|
6
|
+
attr_reader :value
|
5
7
|
|
6
|
-
|
7
|
-
@value = value
|
8
|
-
end
|
8
|
+
delegate :+, to: :value
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
def initialize(value)
|
11
|
+
@value = value
|
12
|
+
end
|
13
|
+
|
14
|
+
def as_json
|
15
|
+
{ val: value }
|
16
|
+
end
|
13
17
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
+
def eql?(other)
|
19
|
+
return true if equals?(other)
|
20
|
+
return false unless other.is_a?(self.class)
|
21
|
+
a.value == value
|
22
|
+
end
|
23
|
+
end
|
18
24
|
end
|
19
25
|
end
|
@@ -1,12 +1,17 @@
|
|
1
|
-
|
2
|
-
def initialize(*array)
|
3
|
-
@array = array
|
4
|
-
end
|
1
|
+
# frozen_string_literal: true
|
5
2
|
|
6
|
-
|
3
|
+
class Hash
|
4
|
+
class ValueChanger
|
5
|
+
class DummyIteractor
|
6
|
+
def initialize(*array)
|
7
|
+
@array = array
|
8
|
+
end
|
7
9
|
|
8
|
-
|
10
|
+
delegate :each, :map, :to_a, to: :array
|
9
11
|
|
10
|
-
|
11
|
-
end
|
12
|
+
private
|
12
13
|
|
14
|
+
attr_reader :array
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1,11 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
shared_examples 'a method that returns a random element' do |method|
|
2
|
-
let(:array) { [
|
4
|
+
let(:array) { [7, 5, 3] }
|
3
5
|
|
4
6
|
(0..2).each do |index|
|
5
7
|
context "when random returns #{index}" do
|
6
8
|
let!(:expected) { array[index] }
|
7
9
|
before do
|
8
|
-
allow_any_instance_of(Array).to receive(:rand)
|
10
|
+
allow_any_instance_of(Array).to receive(:rand)
|
11
|
+
.with(array.size) { index }
|
9
12
|
end
|
10
13
|
|
11
14
|
it 'returns the randomized index of the array' do
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
shared_examples 'a hash clean method' do |method|
|
2
4
|
context 'when hash has one level' do
|
3
5
|
let(:subject) do
|
@@ -29,7 +31,11 @@ shared_examples 'a hash clean method' do |method|
|
|
29
31
|
|
30
32
|
context 'when hash has many levels' do
|
31
33
|
let(:subject) do
|
32
|
-
{
|
34
|
+
{
|
35
|
+
a: 1,
|
36
|
+
d: { e: { k: { l: { m: { n: 1 } } } } },
|
37
|
+
f: { g: { h: { i: { j: { c: '' } } } } }
|
38
|
+
}
|
33
39
|
end
|
34
40
|
|
35
41
|
let(:expected) do
|
@@ -129,7 +135,13 @@ shared_examples 'an array clean method' do |method|
|
|
129
135
|
|
130
136
|
context 'when array has many levels' do
|
131
137
|
let(:subject) do
|
132
|
-
[
|
138
|
+
[
|
139
|
+
1,
|
140
|
+
nil,
|
141
|
+
'',
|
142
|
+
{},
|
143
|
+
[[[{ a: [[[[[[[]]]]]]] }]]], [[[[[[[2]]]]]]], [{ a: [2] }]
|
144
|
+
]
|
133
145
|
end
|
134
146
|
|
135
147
|
let(:expected) do
|
@@ -1,6 +1,10 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
shared_examples 'an object with capable of performing chain fetch' do
|
4
|
+
describe '#chain_fetch' do
|
3
5
|
let(:value) { 10 }
|
6
|
+
let(:keys) { %i[a b c d] }
|
7
|
+
let(:block) { nil }
|
4
8
|
let(:hash) do
|
5
9
|
{
|
6
10
|
b: 1, c: 2, d: 3, a: {
|
@@ -12,8 +16,6 @@ shared_examples 'an object with chain_fetch method' do
|
|
12
16
|
}
|
13
17
|
}
|
14
18
|
end
|
15
|
-
let(:keys) { [:a, :b, :c, :d] }
|
16
|
-
let(:result) { hash.chain_fetch(*keys) }
|
17
19
|
|
18
20
|
context 'when fetching existing keys' do
|
19
21
|
it 'returns the value' do
|
@@ -22,7 +24,7 @@ shared_examples 'an object with chain_fetch method' do
|
|
22
24
|
end
|
23
25
|
|
24
26
|
context 'when fetching non existing keys keys' do
|
25
|
-
let(:keys) { [
|
27
|
+
let(:keys) { %i[a x y] }
|
26
28
|
|
27
29
|
context 'when there is no default value' do
|
28
30
|
it 'raises fetch error' do
|
@@ -50,7 +52,7 @@ shared_examples 'an object with chain_fetch method' do
|
|
50
52
|
|
51
53
|
context 'but a default value block is given' do
|
52
54
|
let(:default_value) { 100 }
|
53
|
-
let(:
|
55
|
+
let(:block) { proc { default_value } }
|
54
56
|
|
55
57
|
it 'returns the default_value' do
|
56
58
|
expect(result).to eq(default_value)
|
@@ -68,7 +70,7 @@ shared_examples 'an object with chain_fetch method' do
|
|
68
70
|
end
|
69
71
|
|
70
72
|
context 'and the block uses the key for the return' do
|
71
|
-
let(:
|
73
|
+
let(:block) { proc { |k| "returned #{k}" } }
|
72
74
|
it 'hnadles the missing keys' do
|
73
75
|
expect(result).to eq('returned x')
|
74
76
|
end
|
data/spec/support/shared_examples/{chain_hash_keys_changer.rb → hash/chain_hash_keys_changer.rb}
RENAMED
@@ -1,25 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
shared_examples 'a class with chain_change_key method' do
|
2
4
|
let(:hash) do
|
3
5
|
{ 'a' => 1, b: 2, c: { d: 3, e: 4 }, f: [{ g: 5 }, { h: 6 }] }
|
4
6
|
end
|
5
7
|
|
6
8
|
describe :chain_change_keys do
|
7
|
-
|
8
|
-
|
9
|
+
it_behaves_like 'a method that is able to chain change keys',
|
10
|
+
:chain_change_keys
|
9
11
|
it 'does not affects the original hash' do
|
10
12
|
expect do
|
11
13
|
hash.chain_change_keys(:to_s, :upcase)
|
12
|
-
end.not_to
|
14
|
+
end.not_to(change { hash })
|
13
15
|
end
|
14
16
|
end
|
15
17
|
|
16
18
|
describe :ichain_change_keys! do
|
17
|
-
it_behaves_like 'a method that is able to chain change keys',
|
19
|
+
it_behaves_like 'a method that is able to chain change keys',
|
20
|
+
:chain_change_keys!
|
18
21
|
|
19
22
|
it 'affects the original hash' do
|
20
23
|
expect do
|
21
24
|
hash.chain_change_keys!(:to_s, :upcase)
|
22
|
-
end.to
|
25
|
+
end.to(change { hash })
|
23
26
|
end
|
24
27
|
end
|
25
28
|
end
|
@@ -27,13 +30,13 @@ end
|
|
27
30
|
shared_examples 'a method that is able to chain change keys' do |method|
|
28
31
|
let(:result) { hash.public_send(method, *transformations, options) }
|
29
32
|
let(:options) { {} }
|
30
|
-
let(:transformations) { [
|
33
|
+
let(:transformations) { [:to_s] }
|
31
34
|
|
32
35
|
context 'with simple level hash' do
|
33
36
|
let(:hash) { { 'a' => 1, b: 2 } }
|
34
37
|
|
35
38
|
context 'with symbol transformation' do
|
36
|
-
let(:transformations) { [
|
39
|
+
let(:transformations) { [:to_sym] }
|
37
40
|
let(:expected) { { a: 1, b: 2 } }
|
38
41
|
it_behaves_like 'result is as expected'
|
39
42
|
end
|
@@ -45,9 +48,9 @@ shared_examples 'a method that is able to chain change keys' do |method|
|
|
45
48
|
end
|
46
49
|
|
47
50
|
context 'with recursive hash' do
|
48
|
-
let(:hash) { { 'a' => 1, b:
|
51
|
+
let(:hash) { { 'a' => 1, b: { c: 3, 'd' => 4 } } }
|
49
52
|
let(:expected) do
|
50
|
-
{ 'a' => 1, 'b' =>
|
53
|
+
{ 'a' => 1, 'b' => { 'c' => 3, 'd' => 4 } }
|
51
54
|
end
|
52
55
|
|
53
56
|
context 'when no options are given' do
|
@@ -64,7 +67,7 @@ shared_examples 'a method that is able to chain change keys' do |method|
|
|
64
67
|
|
65
68
|
context 'without recursion' do
|
66
69
|
let(:recursive) { false }
|
67
|
-
let(:expected) { { 'a' => 1, 'b' =>
|
70
|
+
let(:expected) { { 'a' => 1, 'b' => { c: 3, 'd' => 4 } } }
|
68
71
|
it_behaves_like 'result is as expected'
|
69
72
|
end
|
70
73
|
end
|
@@ -79,7 +82,7 @@ shared_examples 'a method that is able to chain change keys' do |method|
|
|
79
82
|
end
|
80
83
|
|
81
84
|
context 'calling with chained transformations' do
|
82
|
-
let(:transformations) { [
|
85
|
+
let(:transformations) { %i[to_s upcase to_sym] }
|
83
86
|
|
84
87
|
let(:hexpected) do
|
85
88
|
{ A: 1, B: 2, C: { D: 3, E: 4 }, F: [{ G: 5 }, { H: 6 }] }
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
shared_examples 'a class with change_key method' do
|
2
4
|
let(:hash) do
|
3
5
|
{ 'a' => 1, b: 2, c: { d: 3, e: 4 }, f: [{ g: 5 }, { h: 6 }] }
|
@@ -8,7 +10,7 @@ shared_examples 'a class with change_key method' do
|
|
8
10
|
it 'does not affects the original hash' do
|
9
11
|
expect do
|
10
12
|
hash.change_keys(recursive: true) { |k| "foo_#{k}" }
|
11
|
-
end.not_to
|
13
|
+
end.not_to(change { hash })
|
12
14
|
end
|
13
15
|
end
|
14
16
|
|
@@ -18,7 +20,7 @@ shared_examples 'a class with change_key method' do
|
|
18
20
|
it 'affects the original hash' do
|
19
21
|
expect do
|
20
22
|
hash.change_keys!(recursive: true) { |k| "foo_#{k}" }
|
21
|
-
end.to
|
23
|
+
end.to(change { hash })
|
22
24
|
end
|
23
25
|
end
|
24
26
|
end
|
@@ -47,10 +49,10 @@ shared_examples 'a method that is able to change keys' do |method|
|
|
47
49
|
end
|
48
50
|
|
49
51
|
context 'with recursive hash' do
|
50
|
-
let(:hash) { { 'a' => 1, b:
|
52
|
+
let(:hash) { { 'a' => 1, b: { c: 3, 'd' => 4 } } }
|
51
53
|
let(:result) { hash.public_send(method, options) { |k| "foo_#{k}" } }
|
52
54
|
let(:expected) do
|
53
|
-
{ 'foo_a' => 1, 'foo_b' =>
|
55
|
+
{ 'foo_a' => 1, 'foo_b' => { 'foo_c' => 3, 'foo_d' => 4 } }
|
54
56
|
end
|
55
57
|
|
56
58
|
context 'when no options are given' do
|
@@ -68,7 +70,7 @@ shared_examples 'a method that is able to change keys' do |method|
|
|
68
70
|
|
69
71
|
context 'without recursion' do
|
70
72
|
let(:recursive) { false }
|
71
|
-
let(:expected) { { 'foo_a' => 1, 'foo_b' =>
|
73
|
+
let(:expected) { { 'foo_a' => 1, 'foo_b' => { c: 3, 'd' => 4 } } }
|
72
74
|
it_behaves_like 'result is as expected'
|
73
75
|
end
|
74
76
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
shared_examples 'a class that has a method to squash a hash' do
|
6
|
+
describe '#squash' do
|
7
|
+
let(:hash) { { a: { b: 1, c: { d: 2 } } } }
|
8
|
+
|
9
|
+
it 'flattens the hash' do
|
10
|
+
expect(squashed).to eq('a.b' => 1, 'a.c.d' => 2)
|
11
|
+
end
|
12
|
+
|
13
|
+
it { expect { hash.squash }.not_to(change { hash }) }
|
14
|
+
|
15
|
+
context 'with array value' do
|
16
|
+
let(:hash) { { a: { b: [1, { x: 3, y: { z: 4 } }] } } }
|
17
|
+
|
18
|
+
it 'flattens the hash' do
|
19
|
+
expect(squashed).to eq('a.b' => [1, { x: 3, y: { z: 4 } }])
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
shared_examples 'a class with transpose method' do |method|
|
2
4
|
let(:hash) { { a: 1 } }
|
3
5
|
|
@@ -61,7 +63,7 @@ shared_examples 'a class with transpose method' do |method|
|
|
61
63
|
end
|
62
64
|
|
63
65
|
context 'when there is a clash of keys' do
|
64
|
-
let(:hash) { { a: :b, c: :b} }
|
66
|
+
let(:hash) { { a: :b, c: :b } }
|
65
67
|
|
66
68
|
it 'uses the last key for value' do
|
67
69
|
expect(hash.public_send(method)).to eq(b: :c)
|
@@ -69,7 +71,7 @@ shared_examples 'a class with transpose method' do |method|
|
|
69
71
|
end
|
70
72
|
|
71
73
|
context 'when there is a key which alreay has been defined' do
|
72
|
-
let(:hash) { { a: :b, b: :c} }
|
74
|
+
let(:hash) { { a: :b, b: :c } }
|
73
75
|
|
74
76
|
it 'does not override values' do
|
75
77
|
expect(hash.public_send(method)).to eq(b: :a, c: :b)
|
@@ -83,18 +85,18 @@ shared_examples 'a class with transpose method' do |method|
|
|
83
85
|
end
|
84
86
|
|
85
87
|
shared_examples 'a class with transpose methods' do
|
86
|
-
|
88
|
+
it_behaves_like 'a class with transpose method', :transpose do
|
87
89
|
it do
|
88
90
|
expect do
|
89
91
|
hash.transpose
|
90
|
-
end.not_to
|
92
|
+
end.not_to(change { hash })
|
91
93
|
end
|
92
94
|
end
|
93
|
-
|
95
|
+
it_behaves_like 'a class with transpose method', :transpose! do
|
94
96
|
it do
|
95
97
|
expect do
|
96
98
|
hash.transpose!
|
97
|
-
end.to
|
99
|
+
end.to(change { hash })
|
98
100
|
end
|
99
101
|
end
|
100
102
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
shared_examples 'a class with append_keys method' do
|
4
|
+
describe '#prepend_to_keys' do
|
5
|
+
it 'accepts block to change the keys' do
|
6
|
+
hash = { a: 1, 'b' => 2 }
|
7
|
+
expected = { foo_a: 1, 'foo_b' => 2 }
|
8
|
+
expect(hash.prepend_to_keys('foo_')).to eq(expected)
|
9
|
+
end
|
10
|
+
it 'applies the block recursively' do
|
11
|
+
hash = { 'a' => 1, b: { c: 3, 'd' => 4 } }
|
12
|
+
expected = { 'foo_a' => 1, foo_b: { foo_c: 3, 'foo_d' => 4 } }
|
13
|
+
expect(hash.prepend_to_keys('foo_')).to eq(expected)
|
14
|
+
end
|
15
|
+
it 'changes type when type option is passed' do
|
16
|
+
hash = { 'a' => 1, b: 2 }
|
17
|
+
expected = { 'foo_a' => 1, 'foo_b' => 2 }
|
18
|
+
expect(hash.prepend_to_keys('foo_', type: :string)).to eq(expected)
|
19
|
+
end
|
20
|
+
it 'changes type when type option is passed' do
|
21
|
+
hash = { 'a' => 1, b: 2 }
|
22
|
+
expected = { foo_a: 1, foo_b: 2 }
|
23
|
+
expect(hash.prepend_to_keys('foo_', type: :symbol)).to eq(expected)
|
24
|
+
end
|
25
|
+
it 'keep type when type option is passed as keep' do
|
26
|
+
hash = { 'a' => 1, b: 2 }
|
27
|
+
expected = { 'foo_a' => 1, foo_b: 2 }
|
28
|
+
expect(hash.prepend_to_keys('foo_', type: :keep)).to eq(expected)
|
29
|
+
end
|
30
|
+
it 'applies to array as well' do
|
31
|
+
hash = { 'a' => 1, b: [{ c: 2 }, { d: 3 }] }
|
32
|
+
expected = { 'foo_a' => 1, foo_b: [{ foo_c: 2 }, { foo_d: 3 }] }
|
33
|
+
expect(hash.prepend_to_keys('foo_', type: :keep)).to eq(expected)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#append_to_keys' do
|
38
|
+
it 'accepts block to change the keys' do
|
39
|
+
hash = { a: 1, 'b' => 2 }
|
40
|
+
expected = { a_bar: 1, 'b_bar' => 2 }
|
41
|
+
expect(hash.append_to_keys('_bar')).to eq(expected)
|
42
|
+
end
|
43
|
+
it 'applies the block recursively' do
|
44
|
+
hash = { 'a' => 1, b: { c: 3, 'd' => 4 } }
|
45
|
+
expected = { 'a_bar' => 1, b_bar: { c_bar: 3, 'd_bar' => 4 } }
|
46
|
+
expect(hash.append_to_keys('_bar')).to eq(expected)
|
47
|
+
end
|
48
|
+
it 'changes type when type option is passed' do
|
49
|
+
hash = { 'a' => 1, b: 2 }
|
50
|
+
expected = { 'a_bar' => 1, 'b_bar' => 2 }
|
51
|
+
expect(hash.append_to_keys('_bar', type: :string)).to eq(expected)
|
52
|
+
end
|
53
|
+
it 'changes type when type option is passed' do
|
54
|
+
hash = { 'a' => 1, b: 2 }
|
55
|
+
expected = { a_bar: 1, b_bar: 2 }
|
56
|
+
expect(hash.append_to_keys('_bar', type: :symbol)).to eq(expected)
|
57
|
+
end
|
58
|
+
it 'keep type when type option is passed as keep' do
|
59
|
+
hash = { 'a' => 1, b: 2 }
|
60
|
+
expected = { 'a_bar' => 1, b_bar: 2 }
|
61
|
+
expect(hash.append_to_keys('_bar', type: :keep)).to eq(expected)
|
62
|
+
end
|
63
|
+
it 'applies to array as well' do
|
64
|
+
hash = { 'a' => 1, b: [{ c: 2 }, { d: 3 }] }
|
65
|
+
expected = { 'a_bar' => 1, b_bar: [{ c_bar: 2 }, { d_bar: 3 }] }
|
66
|
+
expect(hash.append_to_keys('_bar', type: :keep)).to eq(expected)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
shared_examples 'a class with camlize_keys method' do
|
2
4
|
describe :lower_camelize_keys do
|
3
5
|
let(:expected) { { inputKey: 'value' } }
|
@@ -10,7 +12,7 @@ shared_examples 'a class with camlize_keys method' do
|
|
10
12
|
end
|
11
13
|
|
12
14
|
it 'does not change original hash' do
|
13
|
-
expect { hash.lower_camelize_keys }.not_to
|
15
|
+
expect { hash.lower_camelize_keys }.not_to(change { hash })
|
14
16
|
end
|
15
17
|
end
|
16
18
|
|
@@ -81,7 +83,7 @@ shared_examples 'a class with camlize_keys method' do
|
|
81
83
|
end
|
82
84
|
|
83
85
|
it 'does not change original hash' do
|
84
|
-
expect { hash.lower_camelize_keys! }.to
|
86
|
+
expect { hash.lower_camelize_keys! }.to(change { hash })
|
85
87
|
end
|
86
88
|
end
|
87
89
|
|
@@ -152,7 +154,7 @@ shared_examples 'a class with camlize_keys method' do
|
|
152
154
|
end
|
153
155
|
|
154
156
|
it 'does not change original hash' do
|
155
|
-
expect { hash.camelize_keys }.not_to
|
157
|
+
expect { hash.camelize_keys }.not_to(change { hash })
|
156
158
|
end
|
157
159
|
end
|
158
160
|
|
@@ -223,7 +225,7 @@ shared_examples 'a class with camlize_keys method' do
|
|
223
225
|
end
|
224
226
|
|
225
227
|
it 'does not change original hash' do
|
226
|
-
expect { hash.camelize_keys! }.to
|
228
|
+
expect { hash.camelize_keys! }.to(change { hash })
|
227
229
|
end
|
228
230
|
end
|
229
231
|
|