darthjee-core_ext 1.7.4 → 2.0.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.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +7 -1
  3. data/.gitignore +2 -0
  4. data/.reek.yml +3 -0
  5. data/ARRAY_README.md +72 -15
  6. data/CLASS_README.md +154 -0
  7. data/DATE_README.md +19 -9
  8. data/Dockerfile +2 -5
  9. data/ENUMERABLE_README.md +154 -4
  10. data/HASH_README.md +276 -135
  11. data/MATH_README.md +14 -10
  12. data/OBJECT_README.md +18 -35
  13. data/README.md +8 -4
  14. data/Rakefile +1 -0
  15. data/SYMBOL_README.md +13 -18
  16. data/config/rubycritc.rb +12 -0
  17. data/config/yardstick.yml +45 -3
  18. data/core_ext.gemspec +10 -8
  19. data/docker-compose.yml +15 -7
  20. data/lib/darthjee/core_ext/array.rb +17 -12
  21. data/lib/darthjee/core_ext/array/hash_builder.rb +20 -4
  22. data/lib/darthjee/core_ext/class.rb +28 -10
  23. data/lib/darthjee/core_ext/date.rb +1 -0
  24. data/lib/darthjee/core_ext/enumerable.rb +67 -30
  25. data/lib/darthjee/core_ext/hash.rb +4 -2
  26. data/lib/darthjee/core_ext/hash/cameliazable.rb +39 -8
  27. data/lib/darthjee/core_ext/hash/chain_fetcher.rb +17 -1
  28. data/lib/darthjee/core_ext/hash/changeable.rb +88 -0
  29. data/lib/darthjee/core_ext/hash/deep_hash_constructor.rb +127 -63
  30. data/lib/darthjee/core_ext/hash/deep_hash_constructor/setter.rb +112 -0
  31. data/lib/darthjee/core_ext/hash/key_changeable.rb +126 -54
  32. data/lib/darthjee/core_ext/hash/key_changer.rb +140 -40
  33. data/lib/darthjee/core_ext/hash/keys_sorter.rb +42 -6
  34. data/lib/darthjee/core_ext/hash/squasher.rb +131 -18
  35. data/lib/darthjee/core_ext/hash/transformable.rb +133 -41
  36. data/lib/darthjee/core_ext/hash/transposeable.rb +37 -8
  37. data/lib/darthjee/core_ext/hash/value_changer.rb +76 -36
  38. data/lib/darthjee/core_ext/math.rb +37 -6
  39. data/lib/darthjee/core_ext/numeric.rb +10 -0
  40. data/lib/darthjee/core_ext/object.rb +29 -0
  41. data/lib/darthjee/core_ext/symbol.rb +22 -2
  42. data/lib/darthjee/core_ext/version.rb +1 -1
  43. data/scripts/check_readme.sh +6 -0
  44. data/scripts/rubycritic.sh +10 -0
  45. data/spec/integration/readme/array_spec.rb +96 -0
  46. data/spec/integration/readme/class_spec.rb +123 -0
  47. data/spec/integration/readme/date_spec.rb +20 -0
  48. data/spec/integration/readme/enumerable_spec.rb +87 -0
  49. data/spec/integration/readme/hash_spec.rb +391 -0
  50. data/spec/integration/readme/math_spec.rb +31 -0
  51. data/spec/integration/readme/object_spec.rb +49 -0
  52. data/spec/integration/readme/symbol_spec.rb +29 -0
  53. data/spec/integration/yard/darthjee/core_ext/enumerable_spec.rb +24 -4
  54. data/spec/integration/yard/darthjee/core_ext/hash/cameliazable_spec.rb +11 -0
  55. data/spec/integration/yard/darthjee/core_ext/hash/changeable_spec.rb +68 -0
  56. data/spec/integration/yard/darthjee/core_ext/hash/deep_hash_constructor/setter_spec.rb +34 -0
  57. data/spec/integration/yard/darthjee/core_ext/hash/deep_hash_constructor_spec.rb +65 -0
  58. data/spec/integration/yard/darthjee/core_ext/hash/key_changeable_spec.rb +8 -0
  59. data/spec/integration/yard/darthjee/core_ext/hash/key_changer_spec.rb +59 -0
  60. data/spec/integration/yard/darthjee/core_ext/hash/keys_sorter_spec.rb +25 -0
  61. data/spec/integration/yard/darthjee/core_ext/hash/squasher_spec.rb +60 -0
  62. data/spec/integration/yard/darthjee/core_ext/hash/transformable_spec.rb +66 -36
  63. data/spec/integration/yard/darthjee/core_ext/hash/transposeable_spec.rb +35 -0
  64. data/spec/integration/yard/darthjee/core_ext/hash_spec.rb +13 -2
  65. data/spec/integration/yard/darthjee/core_ext/math_spec.rb +28 -0
  66. data/spec/integration/yard/darthjee/core_ext/numeric_spec.rb +11 -0
  67. data/spec/integration/yard/darthjee/core_ext/object_spec.rb +47 -0
  68. data/spec/integration/yard/darthjee/core_ext/symbol_spec.rb +17 -0
  69. data/spec/lib/darthjee/core_ext/hash/deep_hash_constructor/setter_spec.rb +64 -0
  70. data/spec/lib/darthjee/core_ext/hash/deep_hash_constructor_spec.rb +16 -156
  71. data/spec/lib/darthjee/core_ext/hash/keys_sorter_spec.rb +5 -4
  72. data/spec/lib/darthjee/core_ext/hash/squasher_spec.rb +8 -2
  73. data/spec/lib/darthjee/core_ext/hash/value_changer_spec.rb +4 -12
  74. data/spec/lib/hash_spec.rb +92 -146
  75. data/spec/lib/object_spec.rb +32 -0
  76. data/spec/support/models/client.rb +22 -0
  77. data/spec/support/shared_examples/hash/deep_hash.rb +166 -0
  78. data/spec/support/shared_examples/hash/hash_squasher.rb +54 -9
  79. data/spec/support/shared_examples/hash/keys_sorter.rb +266 -6
  80. metadata +70 -8
  81. data/lib/darthjee/core_ext/hash/to_hash_mapper.rb +0 -25
  82. data/spec/lib/darthjee/core_ext/hash/to_hash_mapper_spec.rb +0 -11
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Symbol do
4
+ describe 'readme' do
5
+ describe '#camelize' do
6
+ it 'camelizes symbol' do
7
+ expect(:underscore_sym.camelize(:upper))
8
+ .to eq(:UnderscoreSym)
9
+ end
10
+
11
+ it 'camelizes symbol lowercasing first letter' do
12
+ expect(:underscore_sym.camelize(:lower))
13
+ .to eq(:underscoreSym)
14
+ end
15
+
16
+ it 'camelizes uppercasing first letter' do
17
+ expect(:underscore_sym.camelize)
18
+ .to eq(:UnderscoreSym)
19
+ end
20
+ end
21
+
22
+ describe '#underscore' do
23
+ it 'underscore symbols' do
24
+ expect(:symBol.underscore)
25
+ .to eq(:sym_bol)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -73,11 +73,31 @@ describe Enumerable do
73
73
  end
74
74
 
75
75
  describe 'map_to_hash' do
76
- subject(:strings) { %w[word big_word] }
76
+ describe 'Mapping strings to their sizes' do
77
+ subject(:strings) { %w[word big_word] }
77
78
 
78
- it 'returns a hash with the mapped values' do
79
- hash = strings.map_to_hash(&:size)
80
- expect(hash).to eq('word' => 4, 'big_word' => 8)
79
+ it 'returns a hash with the mapped values' do
80
+ hash = strings.map_to_hash(&:size)
81
+ expect(hash).to eq('word' => 4, 'big_word' => 8)
82
+ end
83
+ end
84
+
85
+ describe 'Mapping a hash' do
86
+ subject(:hash) { { a: 'word', b: 'bigword', c: 'c' } }
87
+
88
+ let(:new_hash) do
89
+ hash.map_to_hash do |key, value|
90
+ "#{key}->#{value.size}"
91
+ end
92
+ end
93
+
94
+ it 'remaps the values keeping the original keys' do
95
+ expect(new_hash).to eq(
96
+ a: 'a->4',
97
+ b: 'b->7',
98
+ c: 'c->1'
99
+ )
100
+ end
81
101
  end
82
102
  end
83
103
  end
@@ -31,4 +31,15 @@ describe Darthjee::CoreExt::Hash::Cameliazable do
31
31
  expect(result).to eq(firstKey: 1, 'secondKey' => 2)
32
32
  end
33
33
  end
34
+
35
+ describe '#underscore_keys' do
36
+ subject(:hash) do
37
+ { firstKey: 1, 'SecondKey' => 2 }
38
+ end
39
+
40
+ it 'camelize all keys' do
41
+ result = hash.underscore_keys
42
+ expect(result).to eq(first_key: 1, 'second_key' => 2)
43
+ end
44
+ end
34
45
  end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Darthjee::CoreExt::Hash::Changeable do
4
+ describe '#change_values' do
5
+ describe 'Simple usage' do
6
+ subject(:hash) { { a: 1, b: 2 } }
7
+
8
+ it 'changes the values' do
9
+ expect(hash.change_values { |value| value + 1 })
10
+ .to eq(a: 2, b: 3)
11
+ end
12
+ end
13
+
14
+ describe 'Skipping inner hash transformation' do
15
+ subject(:hash) { { a: 1, b: { c: 1 } } }
16
+
17
+ it 'changes the values' do
18
+ expect(hash.change_values(&:to_s))
19
+ .to eq(a: '1', b: { c: '1' })
20
+ end
21
+ end
22
+
23
+ describe 'Not skipping inner hash transformation' do
24
+ subject(:hash) { { a: 1, b: { c: 1 } } }
25
+
26
+ it 'changes the values' do
27
+ expect(hash.change_values(skip_inner: false, &:to_s))
28
+ .to eq(a: '1', b: '{:c=>1}')
29
+ end
30
+ end
31
+ end
32
+
33
+ describe '#change_values!' do
34
+ subject(:hash) { { a: 1, b: inner_hash } }
35
+
36
+ let(:inner_hash) { { c: 2 } }
37
+
38
+ describe 'Changing inner hash' do
39
+ it 'changes the original hash' do
40
+ expect { hash.change_values!(&:to_s) }
41
+ .to change { hash }
42
+ .from(a: 1, b: { c: 2 })
43
+ .to(a: '1', b: { c: '2' })
44
+ end
45
+
46
+ it 'changes the inner hash' do
47
+ expect { hash.change_values!(&:to_s) }
48
+ .to change { inner_hash }
49
+ .from(c: 2)
50
+ .to(c: '2')
51
+ end
52
+ end
53
+
54
+ describe 'Not changing inner hash' do
55
+ it 'changes the original hash' do
56
+ expect { hash.change_values!(skip_inner: false, &:to_s) }
57
+ .to change { hash }
58
+ .from(a: 1, b: { c: 2 })
59
+ .to(a: '1', b: '{:c=>2}')
60
+ end
61
+
62
+ it 'changes the inner hash' do
63
+ expect { hash.change_values!(skip_inner: false, &:to_s) }
64
+ .not_to(change { inner_hash })
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Darthjee::CoreExt::Hash::DeepHashConstructor::Setter do
4
+ subject(:setter) { described_class.new(hash, base_key) }
5
+
6
+ let(:hash) { {} }
7
+ let(:value) { 21 }
8
+
9
+ describe 'yard' do
10
+ describe 'Simple usage' do
11
+ let(:base_key) { 'person' }
12
+ let(:key) { 'age' }
13
+
14
+ it 'set value on inner hash' do
15
+ expect { setter.set(key, value) }
16
+ .to change { hash }
17
+ .from({})
18
+ .to(base_key => { key => value })
19
+ end
20
+ end
21
+
22
+ describe 'with array index' do
23
+ let(:base_key) { 'person[0]' }
24
+ let(:key) { nil }
25
+
26
+ it 'set value on base key array' do
27
+ expect { setter.set(key, value) }
28
+ .to change { hash }
29
+ .from({})
30
+ .to('person' => [value])
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Darthjee::CoreExt::Hash::DeepHashConstructor do
6
+ describe 'yard' do
7
+ subject(:constructor) { described_class.new('.') }
8
+
9
+ let(:hash) do
10
+ {
11
+ 'account.person.name[0]' => 'John',
12
+ 'account.person.name[1]' => 'Wick',
13
+ 'account.person.age' => 20,
14
+ 'account.number' => '102030',
15
+ :'house.number' => 67,
16
+ :'house.zip' => 12_345
17
+ }
18
+ end
19
+
20
+ describe 'general usage' do
21
+ let(:expected) do
22
+ {
23
+ 'account' => {
24
+ 'person' => {
25
+ 'name' => %w[John Wick],
26
+ 'age' => 20
27
+ },
28
+ 'number' => '102030'
29
+ },
30
+ 'house' => {
31
+ 'number' => 67,
32
+ 'zip' => 12_345
33
+ }
34
+ }
35
+ end
36
+
37
+ it 'builds deep hash' do
38
+ expect(constructor.deep_hash(hash))
39
+ .to eq(expected)
40
+ end
41
+ end
42
+
43
+ describe '#break_keys' do
44
+ let(:expected) do
45
+ {
46
+ 'account' => {
47
+ %w[person name[0]] => 'John',
48
+ %w[person name[1]] => 'Wick',
49
+ %w[person age] => 20,
50
+ %w[number] => '102030'
51
+ },
52
+ 'house' => {
53
+ %w[number] => 67,
54
+ %w[zip] => 12_345
55
+ }
56
+ }
57
+ end
58
+
59
+ it 'builds deep hash' do
60
+ expect(constructor.send(:break_keys, hash))
61
+ .to eq(expected)
62
+ end
63
+ end
64
+ end
65
+ end
@@ -45,4 +45,12 @@ describe Darthjee::CoreExt::Hash::KeyChangeable do
45
45
  expect(result).to eq('5': 1, '6': 2)
46
46
  end
47
47
  end
48
+
49
+ describe '#sort_keys' do
50
+ subject(:hash) { { b: 1, a: 2 } }
51
+
52
+ it 'sorts he keys' do
53
+ expect(hash.sort_keys).to eq(a: 2, b: 1)
54
+ end
55
+ end
48
56
  end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Darthjee::CoreExt::Hash::KeyChanger do
6
+ describe 'yard' do
7
+ subject(:changer) { described_class.new(hash) }
8
+
9
+ describe '#remap' do
10
+ let(:hash) { { a: 1, 'b' => 2 } }
11
+
12
+ let(:remap_map) { { a: :za, b: :zb, 'b' => 'yb' } }
13
+
14
+ it 'changes keys using the map' do
15
+ expect { changer.remap(remap_map) }
16
+ .to change { hash }.to(za: 1, 'yb' => 2, zb: nil)
17
+ end
18
+ end
19
+
20
+ describe '#change_keys' do
21
+ let(:hash) { { a: 1, 'b' => { c: 3 } } }
22
+ let(:expected) do
23
+ { 'key_a' => 1, 'key_b' => { 'key_c' => 3 } }
24
+ end
25
+
26
+ it 'changes keys using block' do
27
+ expect { changer.change_keys { |k| "key_#{k}" } }
28
+ .to change { hash }.to(expected)
29
+ end
30
+ end
31
+
32
+ describe '#camelize_keys' do
33
+ let(:hash) { { my_key: { inner_key: 10 } } }
34
+
35
+ it 'camelizes all keys' do
36
+ expect { changer.camelize_keys }
37
+ .to change { hash }.to(MyKey: { InnerKey: 10 })
38
+ end
39
+ end
40
+
41
+ describe '#underscore_keys' do
42
+ let(:hash) { { myKey: { InnerKey: 10 } } }
43
+
44
+ it 'camelizes all keys' do
45
+ expect { changer.underscore_keys }
46
+ .to change { hash }.to(my_key: { inner_key: 10 })
47
+ end
48
+ end
49
+
50
+ describe '#change_text' do
51
+ let(:hash) { { key: { inner_key: 10 } } }
52
+
53
+ it 'changes the text of the keys' do
54
+ expect { changer.change_text { |key| key.to_s.upcase } }
55
+ .to change { hash }.to(KEY: { INNER_KEY: 10 })
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Darthjee::CoreExt::Hash::KeysSorter do
6
+ subject(:sorter) { described_class.new(hash) }
7
+
8
+ describe 'yard' do
9
+ describe 'Simple Usage' do
10
+ let(:hash) { { key: 10, a_key: { z: 5, a: 10 } } }
11
+
12
+ it 'sorts the keys' do
13
+ expect(sorter.sort)
14
+ .to eq(a_key: { a: 10, z: 5 }, key: 10)
15
+ end
16
+
17
+ it 'changes the original hash' do
18
+ expect { sorter.sort }
19
+ .to change(hash, :keys)
20
+ .from(%i[key a_key])
21
+ .to(%i[a_key key])
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Darthjee::CoreExt::Hash::Squasher do
4
+ subject(:squasher) { described_class.new }
5
+
6
+ describe '#squash' do
7
+ describe 'Simple Usage' do
8
+ let(:hash) do
9
+ {
10
+ person: [{
11
+ name: %w[John Wick],
12
+ age: 22
13
+ }, {
14
+ name: %w[John Constantine],
15
+ age: 25
16
+ }]
17
+ }
18
+ end
19
+
20
+ let(:expected) do
21
+ {
22
+ 'person[0].name[0]' => 'John',
23
+ 'person[0].name[1]' => 'Wick',
24
+ 'person[0].age' => 22,
25
+ 'person[1].name[0]' => 'John',
26
+ 'person[1].name[1]' => 'Constantine',
27
+ 'person[1].age' => 25
28
+ }
29
+ end
30
+
31
+ it 'squashes the hash' do
32
+ expect(squasher.squash(hash)).to eq(expected)
33
+ end
34
+ end
35
+
36
+ describe 'Passing custom joiner' do
37
+ subject(:squasher) { described_class.new('> ') }
38
+
39
+ let(:hash) do
40
+ {
41
+ person: {
42
+ name: 'John',
43
+ age: 22
44
+ }
45
+ }
46
+ end
47
+
48
+ let(:expected) do
49
+ {
50
+ 'person> name' => 'John',
51
+ 'person> age' => 22
52
+ }
53
+ end
54
+
55
+ it 'squashes the hash' do
56
+ expect(squasher.squash(hash)).to eq(expected)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -10,7 +10,8 @@ describe Hash do
10
10
  let(:other) { { b: 4, 'c' => 5, e: 6 } }
11
11
 
12
12
  it 'merges only the existing keys' do
13
- expect(hash.exclusive_merge(other)).to eq(a: 1, b: 4, c: 3)
13
+ expect(hash.exclusive_merge(other))
14
+ .to eq(a: 1, b: 4, c: 3)
14
15
  end
15
16
 
16
17
  it 'does not change original hash' do
@@ -26,7 +27,8 @@ describe Hash do
26
27
  let(:other) { { b: 4, 'c' => 5, e: 6 } }
27
28
 
28
29
  it 'merges only the existing keys' do
29
- expect(hash.exclusive_merge!(other)).to eq(a: 1, b: 4, c: 3)
30
+ expect(hash.exclusive_merge!(other))
31
+ .to eq(a: 1, b: 4, c: 3)
30
32
  end
31
33
 
32
34
  it 'does not change original hash' do
@@ -37,63 +39,91 @@ describe Hash do
37
39
  end
38
40
  end
39
41
 
40
- describe '#map_to_hash' do
41
- subject(:hash) { { a: 'word', b: 'bigword', c: 'c' } }
42
+ describe '#squash' do
43
+ describe 'Simple Usage' do
44
+ subject(:hash) do
45
+ { name: { first: 'John', last: 'Doe' } }
46
+ end
42
47
 
43
- let(:new_hash) do
44
- hash.map_to_hash do |key, value|
45
- "#{key}->#{value.size}"
48
+ it 'squash the hash into a one level hash' do
49
+ expect(hash.squash)
50
+ .to eq('name.first' => 'John', 'name.last' => 'Doe')
46
51
  end
47
52
  end
48
53
 
49
- it 'remaps the values keeping the original keys' do
50
- expect(new_hash).to eq(
51
- a: 'a->4',
52
- b: 'b->7',
53
- c: 'c->1'
54
- )
55
- end
56
- end
57
-
58
- describe '#squash' do
59
- subject(:hash) { { name: { first: 'John', last: 'Doe' } } }
54
+ describe 'Reverting a #to_deep_hash call' do
55
+ let(:person) { person_data.to_deep_hash }
56
+ let(:person_data) do
57
+ { 'person.name' => 'John', 'person.age' => 23 }
58
+ end
60
59
 
61
- it 'squash the hash into a one level hash' do
62
- expect(hash.squash).to eq('name.first' => 'John', 'name.last' => 'Doe')
60
+ it 'is the reverse operation' do
61
+ expect(person.squash).to eq(person_data)
62
+ end
63
63
  end
64
64
 
65
- context 'when squashing the result of a deep hash' do
66
- let(:person_data) { { 'person.name' => 'John', 'person.age' => 23 } }
67
- let(:person) { person_data.to_deep_hash }
65
+ describe 'Giving a custom joiner' do
66
+ subject(:hash) do
67
+ {
68
+ links: {
69
+ home: '/',
70
+ products: '/products'
71
+ }
72
+ }
73
+ end
68
74
 
69
- it 'is the reverse operation' do
70
- expect(person.squash).to eq(person_data)
75
+ it 'joins keys using custom joiner' do
76
+ expect(hash.squash('> ')).to eq(
77
+ 'links> home' => '/',
78
+ 'links> products' => '/products'
79
+ )
71
80
  end
72
81
  end
73
82
  end
74
83
 
75
84
  describe '#to_deep_hash' do
76
- subject(:hash) { { 'name_first' => 'John', 'name_last' => 'Doe' } }
85
+ describe 'With custom separator' do
86
+ subject(:hash) do
87
+ {
88
+ 'person[0]_name_first' => 'John',
89
+ 'person[0]_name_last' => 'Doe',
90
+ 'person[1]_name_first' => 'John',
91
+ 'person[1]_name_last' => 'Wick'
92
+ }
93
+ end
77
94
 
78
- it 'with custom separator' do
79
- expect(hash.to_deep_hash('_')).to eq(
80
- 'name' => { 'first' => 'John', 'last' => 'Doe' }
81
- )
95
+ let(:expected) do
96
+ {
97
+ 'person' => [{
98
+ 'name' => { 'first' => 'John', 'last' => 'Doe' }
99
+ }, {
100
+ 'name' => { 'first' => 'John', 'last' => 'Wick' }
101
+ }]
102
+ }
103
+ end
104
+
105
+ it 'with custom separator' do
106
+ expect(hash.to_deep_hash('_')).to eq(expected)
107
+ end
82
108
  end
83
109
 
84
- context 'when squashing the result of a deep hash' do
110
+ describe 'Reverting the result of a squash' do
85
111
  let(:person) do
86
112
  {
87
- 'person' => {
88
- 'name' => 'John',
89
- 'age' => 23
90
- }
113
+ person: [{
114
+ name: %w[John Wick],
115
+ age: 22
116
+ }, {
117
+ name: %w[John Constantine],
118
+ age: 25
119
+ }]
91
120
  }
92
121
  end
93
122
  let(:person_data) { person.squash }
94
123
 
95
124
  it 'is the reverse operation' do
96
- expect(person_data.to_deep_hash).to eq(person)
125
+ expect(person_data.to_deep_hash)
126
+ .to eq(person.deep_stringify_keys)
97
127
  end
98
128
  end
99
129
  end