Skip to content

Commit 4eddca8

Browse files
authored
Merge branch 'master' into feat/add-rails-credentials-support
2 parents e22fe5c + fb280e6 commit 4eddca8

File tree

4 files changed

+98
-2
lines changed

4 files changed

+98
-2
lines changed

lib/config.rb

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ module Config
1818
env_separator: '.',
1919
env_converter: :downcase,
2020
env_parse_values: true,
21+
env_parse_arrays: false,
2122
fail_on_missing: false,
2223
file_name: 'settings',
2324
dir_name: 'settings',

lib/config/sources/env_source.rb

+23-2
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,20 @@ class EnvSource
66
attr_reader :separator
77
attr_reader :converter
88
attr_reader :parse_values
9+
attr_reader :parse_arrays
910

1011
def initialize(env,
1112
prefix: Config.env_prefix || Config.const_name,
1213
separator: Config.env_separator,
1314
converter: Config.env_converter,
14-
parse_values: Config.env_parse_values)
15+
parse_values: Config.env_parse_values,
16+
parse_arrays: Config.env_parse_arrays)
1517
@env = env
1618
@prefix = prefix.to_s.split(separator)
1719
@separator = separator
1820
@converter = converter
1921
@parse_values = parse_values
22+
@parse_arrays = parse_arrays
2023
end
2124

2225
def load
@@ -52,10 +55,28 @@ def load
5255
leaf[keys.last] = parse_values ? __value(value) : value
5356
end
5457

55-
hash
58+
parse_arrays ? convert_hashes_to_arrays(hash) : hash
5659
end
5760

5861
private
62+
def convert_hashes_to_arrays(hash)
63+
hash.each_with_object({}) do |(key, value), new_hash|
64+
if value.is_a?(Hash)
65+
value = convert_hashes_to_arrays(value)
66+
if consecutive_numeric_keys?(value.keys)
67+
new_hash[key] = value.keys.sort_by(&:to_i).map { |k| value[k] }
68+
else
69+
new_hash[key] = value
70+
end
71+
else
72+
new_hash[key] = value
73+
end
74+
end
75+
end
76+
77+
def consecutive_numeric_keys?(keys)
78+
keys.map(&:to_i).sort == (0...keys.size).to_a && keys.all? { |k| k == k.to_i.to_s }
79+
end
5980

6081
# Try to convert string to a correct type
6182
def __value(v)

spec/config_env_spec.rb

+31
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
Config.env_separator = '.'
2323
Config.env_converter = :downcase
2424
Config.env_parse_values = true
25+
Config.env_parse_arrays = true
2526
end
2627

2728
it 'should add new setting from ENV variable' do
@@ -96,6 +97,36 @@
9697
end
9798
end
9899

100+
context 'and parsing ENV variables arrays' do
101+
context 'is enabled' do
102+
before :each do
103+
Config.env_parse_arrays = true
104+
end
105+
106+
it 'should recognize ENV variables with subsequent numeric suffixes starting from 0 as array' do
107+
ENV['Settings.SomeConfig.0'] = 'first'
108+
ENV['Settings.SomeConfig.1'] = 'second'
109+
110+
expect(config.someconfig).to eq(['first', 'second'])
111+
end
112+
end
113+
114+
context 'is disabled' do
115+
before :each do
116+
Config.env_parse_arrays = false
117+
end
118+
119+
it 'should not recognize ENV variables with subsequent numeric suffixes starting from 0 as array' do
120+
ENV['Settings.SomeConfig.0'] = 'first'
121+
ENV['Settings.SomeConfig.1'] = 'second'
122+
123+
expect(config.someconfig).to be_a Config::Options
124+
expect(config.someconfig['0']).to eq('first')
125+
expect(config.someconfig['1']).to eq('second')
126+
end
127+
end
128+
end
129+
99130
context 'and custom ENV variables prefix is defined' do
100131
before :each do
101132
Config.env_prefix = 'MyConfig'

spec/sources/env_source_spec.rb

+43
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,49 @@ module Config::Sources
4343
results = source.load
4444
expect(results['action_mailer']['enabled']).to eq('true')
4545
end
46+
47+
describe 'arrays' do
48+
before(:each) do
49+
Config.env_parse_arrays = true
50+
end
51+
52+
let(:source) do
53+
Config.env_converter = nil
54+
EnvSource.new({
55+
'Settings.SomeConfig.0.0' => 'value1',
56+
'Settings.SomeConfig.0.1' => 'value2',
57+
'Settings.SomeConfig.1.1' => 'value3',
58+
'Settings.SomeConfig.1.2' => 'value4',
59+
'Settings.MixedConfig.1.0' => 'value5',
60+
'Settings.MixedConfig.1.1' => 'value6',
61+
'Settings.MixedConfig.1.custom' => 'value7'
62+
})
63+
end
64+
65+
let(:results) { source.load }
66+
67+
context 'when loading nested configurations' do
68+
it 'converts numeric-keyed hashes to arrays' do
69+
expect(results['SomeConfig']).to be_an Array
70+
expect(results['SomeConfig'][0]).to be_an Array
71+
expect(results['SomeConfig'][0][0]).to eq('value1')
72+
expect(results['SomeConfig'][0][1]).to eq('value2')
73+
end
74+
75+
it 'retains hashes for non-sequential numeric keys' do
76+
expect(results['SomeConfig'][1]).to be_a Hash
77+
expect(results['SomeConfig'][1]['1']).to eq('value3')
78+
expect(results['SomeConfig'][1]['2']).to eq('value4')
79+
end
80+
81+
it 'retains hashes for mixed types' do
82+
expect(results['MixedConfig']['1']).to be_a Hash
83+
expect(results['MixedConfig']['1']['0']).to eq('value5')
84+
expect(results['MixedConfig']['1']['1']).to eq('value6')
85+
expect(results['MixedConfig']['1']['custom']).to eq('value7')
86+
end
87+
end
88+
end
4689
end
4790

4891
context 'configuration overrides' do

0 commit comments

Comments
 (0)