Commit 5335b855 authored by allison.browne's avatar allison.browne

Add examples and specs for edge case of InlineHash

Unested symbolic or numeric keys should not be converted to strings.
These changes document that and adds specs reflecting that. Also
makes a minor change to simplify and speed perf in the InlineHash
implementation.
parent 804badac
...@@ -11,13 +11,15 @@ module Gitlab ...@@ -11,13 +11,15 @@ module Gitlab
# #
# { # {
# 'root_param' => 'Root', # 'root_param' => 'Root',
# 12 => 'number',
# symbol: 'symbol',
# nested_param: { # nested_param: {
# key: 'Value' # key: 'Value'
# }, # },
# 'very' => { # 'very' => {
# 'deep' => { # 'deep' => {
# 'nested' => { # 'nested' => {
# 'param' => 'Deep nested value' # 12 => 'Deep nested value'
# } # }
# } # }
# } # }
...@@ -28,15 +30,17 @@ module Gitlab ...@@ -28,15 +30,17 @@ module Gitlab
# #
# { # {
# 'root_param' => 'Root', # 'root_param' => 'Root',
# 12 => 'number',
# symbol: symbol,
# 'nested_param.key' => 'Value', # 'nested_param.key' => 'Value',
# 'very.deep.nested.param' => 'Deep nested value' # 'very.deep.nested.12' => 'Deep nested value'
# } # }
# #
def merge_keys(hash, prefix: nil, connector: '.') def merge_keys(hash, prefix: nil, connector: '.')
result = {} result = {}
base_prefix = prefix ? "#{prefix}#{connector}" : ''
pairs = pairs =
if prefix if prefix
base_prefix = "#{prefix}#{connector}"
hash.map { |key, value| ["#{base_prefix}#{key}", value] } hash.map { |key, value| ["#{base_prefix}#{key}", value] }
else else
hash.to_a hash.to_a
......
...@@ -6,56 +6,93 @@ describe Gitlab::Utils::InlineHash do ...@@ -6,56 +6,93 @@ describe Gitlab::Utils::InlineHash do
describe '.merge_keys' do describe '.merge_keys' do
subject { described_class.merge_keys(source) } subject { described_class.merge_keys(source) }
let(:source) do context 'with string keys' do
{ let(:source) do
nested_param: { {
key: 'Value' nested_param: {
}, key: 'Value'
'root_param' => 'Root', },
'very' => { 'root_param' => 'Root',
'deep' => { 'very' => {
'nested' => { 'deep' => {
'param' => 'Deep nested value' 'nested' => {
'param' => 'Deep nested value'
}
} }
} }
} }
} end
end
it 'transforms a nested hash into a one-level hash' do
is_expected.to eq(
'nested_param.key' => 'Value',
'root_param' => 'Root',
'very.deep.nested.param' => 'Deep nested value'
)
end
it 'retains key insertion order' do
expect(subject.keys)
.to eq(%w(nested_param.key root_param very.deep.nested.param))
end
context 'with a custom connector' do
subject { described_class.merge_keys(source, connector: '::') }
it 'uses the connector to merge keys' do it 'transforms a nested hash into a one-level hash' do
is_expected.to eq( is_expected.to eq(
'nested_param::key' => 'Value', 'nested_param.key' => 'Value',
'root_param' => 'Root', 'root_param' => 'Root',
'very::deep::nested::param' => 'Deep nested value' 'very.deep.nested.param' => 'Deep nested value'
) )
end end
it 'retains key insertion order' do
expect(subject.keys)
.to eq(%w(nested_param.key root_param very.deep.nested.param))
end
context 'with a custom connector' do
subject { described_class.merge_keys(source, connector: '::') }
it 'uses the connector to merge keys' do
is_expected.to eq(
'nested_param::key' => 'Value',
'root_param' => 'Root',
'very::deep::nested::param' => 'Deep nested value'
)
end
end
context 'with a starter prefix' do
subject { described_class.merge_keys(source, prefix: 'options') }
it 'prefixes all the keys' do
is_expected.to eq(
'options.nested_param.key' => 'Value',
'options.root_param' => 'Root',
'options.very.deep.nested.param' => 'Deep nested value'
)
end
end
end end
context 'with a starter prefix' do context 'with un-nested symbol or numeric keys' do
subject { described_class.merge_keys(source, prefix: 'options') } let(:unested_symbol_key_source) do
{
unnested_symbol_key: :unnested_symbol_value,
12 => 22,
nested_symbol_key: {
nested_symbol_key_2: :nested_symbol_value
}
}
end
context 'without prefix' do
subject { described_class.merge_keys(unested_symbol_key_source) }
it 'prefixes all the keys' do it 'converts only nested keys to inline strings' do
is_expected.to eq( is_expected.to eq(
'options.nested_param.key' => 'Value', :unnested_symbol_key => :unnested_symbol_value,
'options.root_param' => 'Root', 12 => 22,
'options.very.deep.nested.param' => 'Deep nested value' 'nested_symbol_key.nested_symbol_key_2' => :nested_symbol_value
) )
end
end
context 'with prefix' do
subject { described_class.merge_keys(unested_symbol_key_source, prefix: 'options') }
it 'converts prefixed keys to inline strings' do
is_expected.to eq(
'options.unnested_symbol_key' => :unnested_symbol_value,
'options.12' => 22,
'options.nested_symbol_key.nested_symbol_key_2' => :nested_symbol_value
)
end
end end
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment