deep_hash_transformer 2.1.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fd4691f4f42a7a731098aeb989eb7f333e5d34a2a627ddb3229653ff8e1a3a6f
4
- data.tar.gz: 95b96a971d5b65f37411ead70ffd93d92624a145e65125a81d992cc238a87978
3
+ metadata.gz: 7e757436383ce13e17ee8e2b68e48d419e2f9f3c2e57fcfa76503e723ecde5e0
4
+ data.tar.gz: 5508770653b53402c6be53f9a3b1c0ea42a899b42760c2844565c3befa4bc54c
5
5
  SHA512:
6
- metadata.gz: f5f0e923fbed861df614b33a0e3465a8ebb24da4020750414ff911b779e07520507d6cf85c44ffa88bb0009b0fffcea192c3743a9ed7c5aa9562b2f28dc12861
7
- data.tar.gz: 99412bba8c0260a5c90cd126726380f0336dfd5570d806b107601ca735edd2295d9fe8f642af9e5ac4b6a401ae8268e26fce8b59210143fabfe89e7274687180
6
+ metadata.gz: 02c165dda7044c595af36f476fe4234dfca724654e4384d971c183f14dadab6a1f9782f58dd5736f2b82962b7811a41fd51350b2a755ef62cfe684b259dd705d
7
+ data.tar.gz: 41ed65816b738a755fdfbf9e97c0c6ef408fa022a16230d504b0acb4f744ef10279f98954b3eb1c22eaf7af552a9ef5a40c61b75e68cfe4f723f444ebd7e9987
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ class DeepHashTransformer
4
+ class Blank
5
+ BLANK_STRING = /\A[[:space:]]*\z/.freeze
6
+
7
+ def self.call(value)
8
+ new(value).blank?
9
+ end
10
+
11
+ def initialize(value)
12
+ @value = value
13
+ end
14
+
15
+ def blank?
16
+ return true unless value
17
+ return value.blank? if value.respond_to?(:blank?)
18
+ return BLANK_STRING.match?(value) if value.is_a?(String)
19
+ return value.empty? if value.respond_to?(:empty?)
20
+
21
+ false
22
+ end
23
+
24
+ private
25
+
26
+ attr_reader :value
27
+ end
28
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './blank'
4
+
5
+ class DeepHashTransformer
6
+ module CollectionOperation
7
+ class << self
8
+ def compact(val)
9
+ case val
10
+ when Array, Hash
11
+ val.compact
12
+ else
13
+ val
14
+ end
15
+ end
16
+
17
+ def compact_blank(val)
18
+ case val
19
+ when Array
20
+ val.reject { |elem| Blank.call(elem) }
21
+ when Hash
22
+ val.reject { |_, v| Blank.call(v) }
23
+ else
24
+ val
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class DeepHashTransformer
4
- module Operation
4
+ module ElementOperation
5
5
  class << self
6
6
  def camel_case(val)
7
7
  pascal_case(val)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class DeepHashTransformer
4
- VERSION = '2.1.0'
4
+ VERSION = '2.2.0'
5
5
  end
@@ -1,10 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'deep_hash_transformer/operation'
3
+ require 'deep_hash_transformer/collection_operation'
4
+ require 'deep_hash_transformer/element_operation'
4
5
  require 'deep_hash_transformer/version'
5
6
 
6
7
  class DeepHashTransformer
7
- OPS = %i[
8
+ ELEMENT_OPS = %i[
8
9
  camel_case
9
10
  dasherize
10
11
  identity
@@ -15,15 +16,22 @@ class DeepHashTransformer
15
16
  underscore
16
17
  ].freeze
17
18
 
19
+ COLLECTION_OPS = %i[
20
+ compact
21
+ compact_blank
22
+ ].freeze
23
+
24
+ OPS = ELEMENT_OPS + COLLECTION_OPS
25
+
18
26
  def initialize(hash)
19
27
  @hash = hash
20
28
  end
21
29
 
22
30
  def tr(*ops)
23
- unknown_transformtions = ops.map(&:to_s) - OPS.map(&:to_s)
24
- if unknown_transformtions.any?
31
+ unknown_transformations = ops.map(&:to_s) - OPS.map(&:to_s)
32
+ if unknown_transformations.any?
25
33
  raise(
26
- ArgumentError, "unknown transformation(s): #{unknown_transformtions.join(',')}"
34
+ ArgumentError, "unknown transformation(s): #{unknown_transformations.join(',')}"
27
35
  )
28
36
  end
29
37
 
@@ -38,20 +46,30 @@ class DeepHashTransformer
38
46
 
39
47
  attr_reader :hash
40
48
 
41
- def transform_value(value, ops)
42
- case value
43
- when Array
44
- value.map { |e| transform_value(e, ops) }
45
- when Hash
46
- value.map { |k, v| [transform_key(k, ops), transform_value(v, ops)] }.to_h
47
- else
48
- value
49
+ def transform_collection(collection, ops)
50
+ ops.inject(collection) do |c, op|
51
+ COLLECTION_OPS.include?(op) ? CollectionOperation.public_send(op, c) : c
49
52
  end
50
53
  end
51
54
 
55
+ def transform_value(value, ops)
56
+ collection = case value
57
+ when Array
58
+ value.map { |e| transform_value(e, ops) }
59
+ when Hash
60
+ value.map { |k, v| [transform_key(k, ops), transform_value(v, ops)] }.to_h
61
+ else
62
+ value
63
+ end
64
+
65
+ transform_collection(collection, ops)
66
+ end
67
+
52
68
  def transform_key(key, ops)
53
69
  return key unless [String, Symbol].include?(key.class)
54
70
 
55
- ops.inject(key) { |k, op| Operation.public_send(op, k) }
71
+ ops.inject(key) do |k, op|
72
+ ELEMENT_OPS.include?(op) ? ElementOperation.public_send(op, k) : k
73
+ end
56
74
  end
57
75
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe DeepHashTransformer::Blank do
4
+ describe '.call' do
5
+ subject { described_class.call(value) }
6
+
7
+ presents = [true, 1, 0, 'any', [nil], { A: nil }]
8
+ blanks = [nil, false, '', ' ', [], {}]
9
+
10
+ presents.each do |value|
11
+ context "with #{value.inspect}" do
12
+ let(:value) { value }
13
+
14
+ it { is_expected.to be false }
15
+ end
16
+ end
17
+
18
+ blanks.each do |value|
19
+ context "with #{value.inspect}" do
20
+ let(:value) { value }
21
+
22
+ it { is_expected.to be true }
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe DeepHashTransformer::CollectionOperation do
4
+ examples = [
5
+ { a: 'b' }, { a: nil }, { a: ' ' }, [:foo], ['', nil]
6
+ ]
7
+
8
+ subject do
9
+ examples.map { |value| described_class.public_send(method, value) }
10
+ end
11
+
12
+ describe '.compact' do
13
+ let(:method) { :compact }
14
+
15
+ expected_output = [
16
+ { a: 'b' }, {}, { a: ' ' }, [:foo], ['']
17
+ ]
18
+
19
+ it { is_expected.to eq(expected_output) }
20
+ end
21
+
22
+ describe '.compact_blank' do
23
+ let(:method) { :compact_blank }
24
+
25
+ expected_output = [
26
+ { a: 'b' }, {}, {}, [:foo], []
27
+ ]
28
+
29
+ it { is_expected.to eq(expected_output) }
30
+ end
31
+ end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- RSpec.describe DeepHashTransformer::Operation do
3
+ RSpec.describe DeepHashTransformer::ElementOperation do
4
4
  examples = [
5
5
  :symbol, 'string', 'camelCase', 'dashed-key', 'PascalCase', 'under_scored'
6
6
  ]
@@ -22,7 +22,7 @@ RSpec.describe DeepHashTransformer::Operation do
22
22
  }
23
23
  # rubocop:enable Layout/HashAlignment, Style/SymbolArray, Style/WordArray
24
24
 
25
- DeepHashTransformer::OPS.each do |method|
25
+ DeepHashTransformer::ELEMENT_OPS.each do |method|
26
26
  describe "##{method}" do
27
27
  let(:method) { method }
28
28
 
@@ -6,11 +6,11 @@ RSpec.describe DeepHashTransformer do
6
6
  let(:example) { { foo: 'bar' } }
7
7
 
8
8
  describe 'autogenerated methods' do
9
- DeepHashTransformer::OPS.each do |method|
9
+ DeepHashTransformer::ELEMENT_OPS.each do |method|
10
10
  describe ".#{method}" do
11
11
  it "delegates to `Operation.#{method}`" do
12
12
  expect(
13
- DeepHashTransformer::Operation
13
+ DeepHashTransformer::ElementOperation
14
14
  ).to receive(method).with(:foo).once # rubocop:disable RSpec/MessageSpies
15
15
 
16
16
  operation.public_send(method)
@@ -71,6 +71,55 @@ RSpec.describe DeepHashTransformer do
71
71
  )
72
72
  end
73
73
  end
74
+
75
+ context 'with nil values' do
76
+ subject { super().tr(:compact, :stringify) }
77
+
78
+ let(:example) do
79
+ { a: { b: ['', nil, :value], c: '', d: nil, e: true, f: false, g: 123, h: [''] } }
80
+ end
81
+
82
+ it do # rubocop:disable RSpec/ExampleLength
83
+ is_expected.to eq( # rubocop:disable RSpec/ImplicitSubject
84
+ 'a' => {
85
+ 'b' => ['', :value],
86
+ 'c' => '',
87
+ 'e' => true,
88
+ 'f' => false,
89
+ 'g' => 123,
90
+ 'h' => ['']
91
+ }
92
+ )
93
+ end
94
+ end
95
+
96
+ context 'with blank values' do
97
+ subject { super().tr(:compact_blank, :stringify) }
98
+
99
+ let(:example) do
100
+ { a: { b: ['', nil, :value], c: '', d: nil, e: true, f: false, g: 123, h: [''] } }
101
+ end
102
+
103
+ it do # rubocop:disable RSpec/ExampleLength
104
+ is_expected.to eq( # rubocop:disable RSpec/ImplicitSubject
105
+ 'a' => {
106
+ 'b' => [:value],
107
+ 'e' => true,
108
+ 'g' => 123
109
+ }
110
+ )
111
+ end
112
+ end
113
+
114
+ context 'with deeply nested blank values' do
115
+ subject { super().tr(:compact_blank) }
116
+
117
+ let(:example) do
118
+ { a: { b: [nil, { c: nil }] } }
119
+ end
120
+
121
+ it { is_expected.to eq({}) }
122
+ end
74
123
  end
75
124
 
76
125
  it 'has a version number' do
data/spec/spec_helper.rb CHANGED
@@ -2,7 +2,9 @@
2
2
 
3
3
  require 'bundler/setup'
4
4
  require 'deep_hash_transformer'
5
- require 'deep_hash_transformer/operation'
5
+ require 'deep_hash_transformer/blank'
6
+ require 'deep_hash_transformer/collection_operation'
7
+ require 'deep_hash_transformer/element_operation'
6
8
  require 'simplecov'
7
9
 
8
10
  SimpleCov.start do
metadata CHANGED
@@ -1,127 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: deep_hash_transformer
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martin Spickermann
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-03-05 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: rake
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: rspec
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: rubocop
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: rubocop-performance
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: rubocop-rake
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: rubocop-rspec
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
- - !ruby/object:Gem::Dependency
98
- name: simplecov
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - ">="
102
- - !ruby/object:Gem::Version
103
- version: '0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- version: '0'
111
- - !ruby/object:Gem::Dependency
112
- name: simplecov-lcov
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - ">="
116
- - !ruby/object:Gem::Version
117
- version: '0'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - ">="
123
- - !ruby/object:Gem::Version
124
- version: '0'
11
+ date: 2023-05-16 00:00:00.000000000 Z
12
+ dependencies: []
125
13
  description: " DeepHashTransformer helps to transform keys in deeply nested hash
126
14
  structures\n"
127
15
  email:
@@ -132,9 +20,13 @@ extra_rdoc_files: []
132
20
  files:
133
21
  - MIT-LICENSE
134
22
  - lib/deep_hash_transformer.rb
135
- - lib/deep_hash_transformer/operation.rb
23
+ - lib/deep_hash_transformer/blank.rb
24
+ - lib/deep_hash_transformer/collection_operation.rb
25
+ - lib/deep_hash_transformer/element_operation.rb
136
26
  - lib/deep_hash_transformer/version.rb
137
- - spec/deep_hash_transformer/operation_spec.rb
27
+ - spec/deep_hash_transformer/blank_spec.rb
28
+ - spec/deep_hash_transformer/collection_operation_spec.rb
29
+ - spec/deep_hash_transformer/element_operation_spec.rb
138
30
  - spec/deep_hash_transformer_spec.rb
139
31
  - spec/spec_helper.rb
140
32
  homepage: https://github.com/spickermann/deep_hash_transformer
@@ -157,7 +49,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
157
49
  - !ruby/object:Gem::Version
158
50
  version: '0'
159
51
  requirements: []
160
- rubygems_version: 3.3.3
52
+ rubygems_version: 3.4.10
161
53
  signing_key:
162
54
  specification_version: 4
163
55
  summary: Transforms deeply nested hash structure