deep_hash_transformer 2.0.0 → 2.1.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: 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