deep_hash_transformer 2.0.0 → 2.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a7f171270350f94fdce54754d2cd72e7832b50d96fd92255e7c0ccf2b4a4460b
4
- data.tar.gz: bfbe82ac975f7a38f21a26ffd969fb226592ec67e4d54c6009213ad56883e146
3
+ metadata.gz: fd4691f4f42a7a731098aeb989eb7f333e5d34a2a627ddb3229653ff8e1a3a6f
4
+ data.tar.gz: 95b96a971d5b65f37411ead70ffd93d92624a145e65125a81d992cc238a87978
5
5
  SHA512:
6
- metadata.gz: 3c2b9b9c03df98e7407c1ff2e365b2b49a5e200380b1a3747be28d3bcdb8832be8c59c5b94db2753b93809549d7841da2bf1e0a9d6bb425c1c9f545802bea830
7
- data.tar.gz: cab7709f4bf6dbb2a3c9d692c0d3bb4af83b4ce318a020624ad7151c7e1d71f40dde2dec2df51326d79e0f9ae7f2a97c72ba11c65c38467e3e617d26bb572d1f
6
+ metadata.gz: f5f0e923fbed861df614b33a0e3465a8ebb24da4020750414ff911b779e07520507d6cf85c44ffa88bb0009b0fffcea192c3743a9ed7c5aa9562b2f28dc12861
7
+ data.tar.gz: 99412bba8c0260a5c90cd126726380f0336dfd5570d806b107601ca735edd2295d9fe8f642af9e5ac4b6a401ae8268e26fce8b59210143fabfe89e7274687180
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ class DeepHashTransformer
4
+ module Operation
5
+ class << self
6
+ def camel_case(val)
7
+ pascal_case(val)
8
+ .sub(/^[A-Z]/, &:downcase)
9
+ end
10
+
11
+ def dasherize(val)
12
+ stringify(val)
13
+ .tr('_', '-')
14
+ end
15
+
16
+ def identity(val)
17
+ val
18
+ end
19
+
20
+ def pascal_case(val)
21
+ stringify(val)
22
+ .split(/(?=[A-Z])|[-_]/)
23
+ .map(&:capitalize)
24
+ .join
25
+ end
26
+
27
+ def stringify(val)
28
+ val.to_s
29
+ end
30
+
31
+ def symbolize(val)
32
+ val.to_sym
33
+ end
34
+
35
+ def underscore(val)
36
+ stringify(val)
37
+ .tr('-', '_')
38
+ end
39
+
40
+ def snake_case(val)
41
+ stringify(val)
42
+ .gsub(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
43
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2')
44
+ .tr('-', '_')
45
+ .downcase
46
+ end
47
+ end
48
+ end
49
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class DeepHashTransformer
4
- VERSION = '2.0.0'
4
+ VERSION = '2.1.0'
5
5
  end
@@ -1,25 +1,36 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'deep_hash_transformer/operation'
3
4
  require 'deep_hash_transformer/version'
4
5
 
5
6
  class DeepHashTransformer
6
- OPS = {
7
- dasherize: ->(val) { val.to_s.tr('_', '-') },
8
- identity: ->(val) { val },
9
- stringify: ->(val) { val.to_s },
10
- symbolize: ->(val) { val.to_sym },
11
- underscore: ->(val) { val.to_s.tr('-', '_') }
12
- }.freeze
7
+ OPS = %i[
8
+ camel_case
9
+ dasherize
10
+ identity
11
+ pascal_case
12
+ snake_case
13
+ stringify
14
+ symbolize
15
+ underscore
16
+ ].freeze
13
17
 
14
18
  def initialize(hash)
15
19
  @hash = hash
16
20
  end
17
21
 
18
22
  def tr(*ops)
23
+ unknown_transformtions = ops.map(&:to_s) - OPS.map(&:to_s)
24
+ if unknown_transformtions.any?
25
+ raise(
26
+ ArgumentError, "unknown transformation(s): #{unknown_transformtions.join(',')}"
27
+ )
28
+ end
29
+
19
30
  transform_value(hash, ops)
20
31
  end
21
32
 
22
- OPS.each_key do |operation|
33
+ OPS.each do |operation|
23
34
  define_method(operation) { tr(operation) }
24
35
  end
25
36
 
@@ -41,6 +52,6 @@ class DeepHashTransformer
41
52
  def transform_key(key, ops)
42
53
  return key unless [String, Symbol].include?(key.class)
43
54
 
44
- ops.inject(key) { |k, op| OPS.fetch(op).call(k) }
55
+ ops.inject(key) { |k, op| Operation.public_send(op, k) }
45
56
  end
46
57
  end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe DeepHashTransformer::Operation do
4
+ examples = [
5
+ :symbol, 'string', 'camelCase', 'dashed-key', 'PascalCase', 'under_scored'
6
+ ]
7
+
8
+ subject do
9
+ examples.map { |value| described_class.public_send(method, value) }
10
+ end
11
+
12
+ # rubocop:disable Layout/HashAlignment, Style/SymbolArray, Style/WordArray
13
+ expected_output = {
14
+ camel_case: ['symbol', 'string', 'camelCase', 'dashedKey', 'pascalCase', 'underScored'],
15
+ dasherize: ['symbol', 'string', 'camelCase', 'dashed-key', 'PascalCase', 'under-scored'],
16
+ identity: [:symbol, 'string', 'camelCase', 'dashed-key', 'PascalCase', 'under_scored'],
17
+ pascal_case: ['Symbol', 'String', 'CamelCase', 'DashedKey', 'PascalCase', 'UnderScored'],
18
+ snake_case: ['symbol', 'string', 'camel_case', 'dashed_key', 'pascal_case', 'under_scored'],
19
+ stringify: ['symbol', 'string', 'camelCase', 'dashed-key', 'PascalCase', 'under_scored'],
20
+ symbolize: [:symbol, :string, :camelCase, :'dashed-key', :PascalCase, :under_scored],
21
+ underscore: ['symbol', 'string', 'camelCase', 'dashed_key', 'PascalCase', 'under_scored']
22
+ }
23
+ # rubocop:enable Layout/HashAlignment, Style/SymbolArray, Style/WordArray
24
+
25
+ DeepHashTransformer::OPS.each do |method|
26
+ describe "##{method}" do
27
+ let(:method) { method }
28
+
29
+ it { is_expected.to eq(expected_output[method]) }
30
+ end
31
+ end
32
+ end
@@ -1,87 +1,79 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  RSpec.describe DeepHashTransformer do
4
- subject do
5
- described_class.new(
6
- Integer => 123,
7
- :foobar => { bar: 'bar' },
8
- 'aa_zz' => [{ 'bar' => :bar, 'a-z' => 'a-z' }]
9
- )
10
- end
4
+ subject(:operation) { described_class.new(example) }
11
5
 
12
- describe '#tr with `:underscore, :symbolize`' do
13
- subject { super().tr(:underscore, :symbolize) }
6
+ let(:example) { { foo: 'bar' } }
14
7
 
15
- it do
16
- expect(subject).to eq( # rubocop:disable RSpec/NamedSubject
17
- Integer => 123,
18
- :foobar => { bar: 'bar' },
19
- :aa_zz => [{ bar: :bar, a_z: 'a-z' }]
20
- )
21
- end
22
- end
8
+ describe 'autogenerated methods' do
9
+ DeepHashTransformer::OPS.each do |method|
10
+ describe ".#{method}" do
11
+ it "delegates to `Operation.#{method}`" do
12
+ expect(
13
+ DeepHashTransformer::Operation
14
+ ).to receive(method).with(:foo).once # rubocop:disable RSpec/MessageSpies
23
15
 
24
- describe '#dasherize' do
25
- subject { super().dasherize }
26
-
27
- it do
28
- expect(subject).to eq( # rubocop:disable RSpec/NamedSubject
29
- Integer => 123,
30
- 'foobar' => { 'bar' => 'bar' },
31
- 'aa-zz' => [{ 'bar' => :bar, 'a-z' => 'a-z' }]
32
- )
16
+ operation.public_send(method)
17
+ end
18
+ end
33
19
  end
34
20
  end
35
21
 
36
- describe '#identity' do
37
- subject { super().identity }
38
-
39
- it do
40
- expect(subject).to eq( # rubocop:disable RSpec/NamedSubject
41
- Integer => 123,
42
- :foobar => { bar: 'bar' },
43
- 'aa_zz' => [{ 'bar' => :bar, 'a-z' => 'a-z' }]
44
- )
45
- end
46
- end
22
+ describe '#tr' do
23
+ context 'with `:snake_case, :symbolize`' do
24
+ subject { super().tr(:snake_case, :symbolize) }
47
25
 
48
- describe '#stringify' do
49
- subject { super().stringify }
26
+ let(:example) { { 'FooBar' => 'baz' } }
50
27
 
51
- it do
52
- expect(subject).to eq( # rubocop:disable RSpec/NamedSubject
53
- Integer => 123,
54
- 'foobar' => { 'bar' => 'bar' },
55
- 'aa_zz' => [{ 'bar' => :bar, 'a-z' => 'a-z' }]
56
- )
28
+ it { is_expected.to eq(foo_bar: 'baz') }
57
29
  end
58
- end
59
30
 
60
- describe '#symbolize' do
61
- subject { super().symbolize }
31
+ context 'with an unknown transformation' do
32
+ subject(:unknown_ops) { operation.tr(:unknown) }
62
33
 
63
- it do
64
- expect(subject).to eq( # rubocop:disable RSpec/NamedSubject
65
- Integer => 123,
66
- :foobar => { bar: 'bar' },
67
- :aa_zz => [{ bar: :bar, 'a-z': 'a-z' }]
68
- )
34
+ it 'raise an exception' do
35
+ expect { unknown_ops }.to raise_error(ArgumentError, /unknown/)
36
+ end
69
37
  end
70
- end
71
38
 
72
- describe '#underscore' do
73
- subject { super().underscore }
39
+ context 'with a complex, nested example' do
40
+ subject { super().tr(:camel_case, :symbolize) }
41
+
42
+ let(:example) do
43
+ {
44
+ Integer => 123,
45
+ :symbol => { foo_bar: 'bar' },
46
+ 'string' => { 'foo_bar' => 123 },
47
+ 'nested-array' => [
48
+ {
49
+ 'camelCased' => 'camelCased',
50
+ 'dashed-key' => 'dashed-key',
51
+ 'PascalCased' => 'PascalCased',
52
+ 'under_scored' => 'under_scored'
53
+ }
54
+ ]
55
+ }
56
+ end
74
57
 
75
- it do
76
- expect(subject).to eq( # rubocop:disable RSpec/NamedSubject
77
- Integer => 123,
78
- 'foobar' => { 'bar' => 'bar' },
79
- 'aa_zz' => [{ 'bar' => :bar, 'a_z' => 'a-z' }]
80
- )
58
+ it do # rubocop:disable RSpec/ExampleLength
59
+ is_expected.to eq( # rubocop:disable RSpec/ImplicitSubject
60
+ Integer => 123,
61
+ :symbol => { fooBar: 'bar' },
62
+ :string => { fooBar: 123 },
63
+ :nestedArray => [
64
+ {
65
+ camelCased: 'camelCased',
66
+ dashedKey: 'dashed-key',
67
+ pascalCased: 'PascalCased',
68
+ underScored: 'under_scored'
69
+ }
70
+ ]
71
+ )
72
+ end
81
73
  end
82
74
  end
83
75
 
84
76
  it 'has a version number' do
85
- expect(DeepHashTransformer::VERSION).not_to be nil
77
+ expect(DeepHashTransformer::VERSION).not_to be_nil
86
78
  end
87
79
  end
data/spec/spec_helper.rb CHANGED
@@ -1,10 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'bundler/setup'
4
- require 'coveralls'
5
4
  require 'deep_hash_transformer'
5
+ require 'deep_hash_transformer/operation'
6
+ require 'simplecov'
6
7
 
7
- Coveralls.wear!
8
+ SimpleCov.start do
9
+ if ENV['CI']
10
+ require 'simplecov-lcov'
11
+
12
+ SimpleCov::Formatter::LcovFormatter.config do |c|
13
+ c.report_with_single_file = true
14
+ c.single_report_path = 'coverage/lcov.info'
15
+ end
16
+
17
+ formatter SimpleCov::Formatter::LcovFormatter
18
+ end
19
+
20
+ add_filter %w[version.rb initializer.rb]
21
+ end
8
22
 
9
23
  RSpec.configure do |config|
10
24
  # Enable flags like --only-failures and --next-failure
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: deep_hash_transformer
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.1.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: 2020-12-28 00:00:00.000000000 Z
11
+ date: 2022-03-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: coveralls
14
+ name: rake
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
@@ -25,7 +25,7 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: rake
28
+ name: rspec
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
@@ -39,7 +39,7 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: rspec
42
+ name: rubocop
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: rubocop
56
+ name: rubocop-performance
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -67,7 +67,7 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: rubocop-performance
70
+ name: rubocop-rake
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ">="
@@ -94,7 +94,36 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
- description: " DeepHashTransformer helps to transform deeply nested hash structures\n"
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'
125
+ description: " DeepHashTransformer helps to transform keys in deeply nested hash
126
+ structures\n"
98
127
  email:
99
128
  - spickermann@gmail.com
100
129
  executables: []
@@ -103,13 +132,16 @@ extra_rdoc_files: []
103
132
  files:
104
133
  - MIT-LICENSE
105
134
  - lib/deep_hash_transformer.rb
135
+ - lib/deep_hash_transformer/operation.rb
106
136
  - lib/deep_hash_transformer/version.rb
137
+ - spec/deep_hash_transformer/operation_spec.rb
107
138
  - spec/deep_hash_transformer_spec.rb
108
139
  - spec/spec_helper.rb
109
140
  homepage: https://github.com/spickermann/deep_hash_transformer
110
141
  licenses:
111
142
  - MIT
112
- metadata: {}
143
+ metadata:
144
+ rubygems_mfa_required: 'true'
113
145
  post_install_message:
114
146
  rdoc_options: []
115
147
  require_paths:
@@ -125,7 +157,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
125
157
  - !ruby/object:Gem::Version
126
158
  version: '0'
127
159
  requirements: []
128
- rubygems_version: 3.2.3
160
+ rubygems_version: 3.3.3
129
161
  signing_key:
130
162
  specification_version: 4
131
163
  summary: Transforms deeply nested hash structure