blueprint_config 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.idea/.gitignore +8 -0
  4. data/.idea/blue_config.iml +72 -0
  5. data/.idea/misc.xml +4 -0
  6. data/.idea/modules.xml +8 -0
  7. data/.idea/vcs.xml +6 -0
  8. data/.rspec +1 -0
  9. data/.ruby-version +1 -0
  10. data/Gemfile +6 -0
  11. data/LICENSE.txt +22 -0
  12. data/README.md +152 -0
  13. data/Rakefile +8 -0
  14. data/blueprint_config.gemspec +31 -0
  15. data/lib/blueprint_config/backend/active_record.rb +51 -0
  16. data/lib/blueprint_config/backend/base.rb +34 -0
  17. data/lib/blueprint_config/backend/credentials.rb +26 -0
  18. data/lib/blueprint_config/backend/env.rb +47 -0
  19. data/lib/blueprint_config/backend/yaml.rb +30 -0
  20. data/lib/blueprint_config/backend_collection.rb +67 -0
  21. data/lib/blueprint_config/configuration.rb +64 -0
  22. data/lib/blueprint_config/options_array.rb +81 -0
  23. data/lib/blueprint_config/options_hash.rb +112 -0
  24. data/lib/blueprint_config/setting.rb +28 -0
  25. data/lib/blueprint_config/version.rb +5 -0
  26. data/lib/blueprint_config/yaml.rb +46 -0
  27. data/lib/blueprint_config.rb +71 -0
  28. data/lib/generators/blueprint_config/install/USAGE +8 -0
  29. data/lib/generators/blueprint_config/install/install_generator.rb +23 -0
  30. data/lib/generators/blueprint_config/install/templates/migration.rb.erb +18 -0
  31. data/spec/backend_collection_spec.rb +103 -0
  32. data/spec/blueprint_config/backend/active_record_spec.rb +41 -0
  33. data/spec/blueprint_config/backend/env_spec.rb +53 -0
  34. data/spec/blueprint_config/backend/yaml_spec.rb +35 -0
  35. data/spec/blueprint_config/options_array_spec.rb +109 -0
  36. data/spec/blueprint_config/options_hash_spec.rb +211 -0
  37. data/spec/config/app.yml +24 -0
  38. data/spec/configuration_spec.rb +98 -0
  39. data/spec/spec_helper.rb +16 -0
  40. metadata +163 -0
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe BlueprintConfig::OptionsArray do
4
+ let(:source) do
5
+ %w[a b c]
6
+ end
7
+ subject { described_class.new(source, source: 'env', path: 'path') }
8
+
9
+ describe '#initialize' do
10
+ it 'succeeds' do
11
+ expect { subject }.not_to raise_error
12
+ end
13
+ end
14
+
15
+ describe 'getting values' do
16
+ it 'retrieves members with []', :aggregate_failures do
17
+ expect(subject[0]).to eq('a')
18
+ expect(subject[1]).to eq('b')
19
+ expect(subject[2]).to eq('c')
20
+ end
21
+ end
22
+
23
+ describe '#dig' do
24
+ it 'retrieves members using position', :aggregate_failures do
25
+ expect(subject[0]).to eq('a')
26
+ expect(subject[1]).to eq('b')
27
+ expect(subject[2]).to eq('c')
28
+ expect(subject[3]).to eq(nil)
29
+ end
30
+ end
31
+
32
+ describe '#dig!' do
33
+ it 'retrieves members using position', :aggregate_failures do
34
+ expect(subject.dig!(0)).to eq('a')
35
+ expect(subject.dig!(1)).to eq('b')
36
+ expect(subject.dig!(2)).to eq('c')
37
+ end
38
+
39
+ it 'raises exception when key not found', :aggregate_failures do
40
+ expect { subject.dig!(3) }.to raise_error(IndexError, "Configuration key 'path.3' is not set")
41
+ end
42
+ end
43
+
44
+ describe '#fetch' do
45
+ it 'retrieves members using position', :aggregate_failures do
46
+ expect(subject.fetch(0)).to eq('a')
47
+ expect(subject.fetch(1)).to eq('b')
48
+ end
49
+
50
+ it 'raise error when key is not present and no block is given', :aggregate_failures do
51
+ expect { subject.fetch(3) }.to raise_error(IndexError, "Configuration key 'path.3' is not set")
52
+ end
53
+
54
+ it 'calls block when it is given and key is not present', :aggregate_failures do
55
+ expect(subject.fetch(3, 1)).to eq(1)
56
+ end
57
+ end
58
+
59
+ describe '#source' do
60
+ it 'returns the source', :aggregate_failures do
61
+ expect(subject.source(0)).to eq('env path.0')
62
+ expect(subject.source(1)).to eq('env path.1')
63
+ expect(subject.source(2)).to eq('env path.2')
64
+ end
65
+
66
+ context 'when out of range' do
67
+ it 'raises exception', :aggregate_failures do
68
+ expect { subject.source(3) }.to raise_error(IndexError, "Configuration key 'path.3' is not set")
69
+ end
70
+ end
71
+
72
+ context 'when merging 2 sources' do
73
+ let(:source1) do
74
+ %w[a b c]
75
+ end
76
+ let(:source2) do
77
+ %w[__append e f]
78
+ end
79
+ let(:options1) { described_class.new(source1, source: 'env1', path: 'path1') }
80
+ let(:options2) { described_class.new(source2, source: 'env2', path: 'path1') }
81
+ subject { options1.__assign(options2) }
82
+
83
+ it 'returns the source correctly', :aggregate_failures do
84
+ expect(subject.source(0)).to eq('env1 path1.0')
85
+ expect(subject.source(1)).to eq('env1 path1.1')
86
+ expect(subject.source(2)).to eq('env1 path1.2')
87
+ expect(subject.source(3)).to eq('env2 path1.1')
88
+ expect(subject.source(4)).to eq('env2 path1.2')
89
+ end
90
+ end
91
+
92
+ context 'when overriding from different source' do
93
+ let(:source1) do
94
+ %w[a b c]
95
+ end
96
+ let(:source2) do
97
+ %w[e f]
98
+ end
99
+ let(:options1) { described_class.new(source1, source: 'env1') }
100
+ let(:options2) { described_class.new(source2, source: 'env2') }
101
+ subject { options1.__assign(options2) }
102
+
103
+ it 'returns the source', :aggregate_failures do
104
+ expect(subject.source(0)).to eq('env2 0')
105
+ expect(subject.source(1)).to eq('env2 1')
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,211 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe BlueprintConfig::OptionsHash do
4
+ let(:source) do
5
+ {
6
+ a: 1,
7
+ b: 2,
8
+ c: {
9
+ d: 1,
10
+ e: 2
11
+ },
12
+ k: [1, 2, 3],
13
+ j: [{ a: 1 }, { b: 2 }]
14
+ }
15
+ end
16
+ subject { described_class.new(source, source: 'env') }
17
+
18
+ describe '#initialize' do
19
+ it 'succeeds' do
20
+ expect { subject }.not_to raise_error
21
+ end
22
+ end
23
+
24
+ describe 'getting values' do
25
+ it 'retrieves members as method calls', :aggregate_failures do
26
+ expect(subject.a).to eq(1)
27
+ expect(subject.b).to eq(2)
28
+ expect(subject.c.d).to eq(1)
29
+ expect(subject.c.e).to eq(2)
30
+ expect(subject.c.f).to eq(nil)
31
+ expect(subject.d).to eq(nil)
32
+ end
33
+
34
+ it 'retrieves members with [] and symbol keys', :aggregate_failures do
35
+ expect(subject[:a]).to eq(1)
36
+ expect(subject[:b]).to eq(2)
37
+ expect(subject[:c][:d]).to eq(1)
38
+ expect(subject[:c][:e]).to eq(2)
39
+ expect(subject[:c][:f]).to eq(nil)
40
+ expect(subject[:d]).to eq(nil)
41
+ end
42
+
43
+ it 'retrieves members with [] and string keys', :aggregate_failures do
44
+ expect(subject['a']).to eq(1)
45
+ expect(subject['b']).to eq(2)
46
+ expect(subject['c']['d']).to eq(1)
47
+ expect(subject['c']['e']).to eq(2)
48
+ expect(subject['c']['f']).to eq(nil)
49
+ expect(subject['d']).to eq(nil)
50
+ end
51
+
52
+ it 'retrieves members with [] and mixed keys', :aggregate_failures do
53
+ expect(subject[:c]['d']).to eq(1)
54
+ expect(subject['c'][:e]).to eq(2)
55
+ expect(subject['c'][:f]).to eq(nil)
56
+ expect(subject[:c]['f']).to eq(nil)
57
+ end
58
+
59
+ it 'retrieves members with [] and array elements', :aggregate_failures do
60
+ expect(subject[:k][0]).to eq(1)
61
+ expect(subject[:k][1]).to eq(2)
62
+ expect(subject[:j][0][:a]).to eq(1)
63
+ expect(subject[:j][1][:b]).to eq(2)
64
+ end
65
+ end
66
+
67
+ describe '#dig' do
68
+ it 'retrieves members using string keys', :aggregate_failures do
69
+ expect(subject['a']).to eq(1)
70
+ expect(subject['b']).to eq(2)
71
+ expect(subject.dig('c', 'd')).to eq(1)
72
+ expect(subject.dig('c', 'e')).to eq(2)
73
+ expect(subject.dig('c', 'f')).to eq(nil)
74
+ expect(subject['d']).to eq(nil)
75
+ end
76
+
77
+ it 'retrieves members using symbol keys', :aggregate_failures do
78
+ expect(subject[:a]).to eq(1)
79
+ expect(subject[:b]).to eq(2)
80
+ expect(subject.dig(:c, :d)).to eq(1)
81
+ expect(subject.dig(:c, :e)).to eq(2)
82
+ expect(subject.dig(:c, :f)).to eq(nil)
83
+ expect(subject[:d]).to eq(nil)
84
+ end
85
+
86
+ it 'retrieves members using mixed keys', :aggregate_failures do
87
+ expect(subject.dig('c', :d)).to eq(1)
88
+ expect(subject.dig(:c, 'e')).to eq(2)
89
+ expect(subject.dig('c', :f)).to eq(nil)
90
+ expect(subject.dig(:c, 'g')).to eq(nil)
91
+ end
92
+
93
+ it 'retrieves members with array elements', :aggregate_failures do
94
+ expect(subject.dig(:k, 0)).to eq(1)
95
+ expect(subject.dig(:k, 1)).to eq(2)
96
+ expect(subject.dig(:j, 0, :a)).to eq(1)
97
+ expect(subject.dig(:j, 1, :b)).to eq(2)
98
+ end
99
+ end
100
+
101
+ describe '#dig!' do
102
+ it 'retrieves members using string keys', :aggregate_failures do
103
+ expect(subject.dig!('a')).to eq(1)
104
+ expect(subject.dig!('b')).to eq(2)
105
+ expect(subject.dig!('c', 'd')).to eq(1)
106
+ expect(subject.dig!('c', 'e')).to eq(2)
107
+ end
108
+
109
+ it 'retrieves members using symbol keys', :aggregate_failures do
110
+ expect(subject.dig!(:a)).to eq(1)
111
+ expect(subject.dig!(:b)).to eq(2)
112
+ expect(subject.dig!(:c, :d)).to eq(1)
113
+ expect(subject.dig!(:c, :e)).to eq(2)
114
+ end
115
+
116
+ it 'retrieves members using mixed keys', :aggregate_failures do
117
+ expect(subject.dig!('c', :d)).to eq(1)
118
+ expect(subject.dig!(:c, 'e')).to eq(2)
119
+ end
120
+
121
+ it 'retrieves members with array elements', :aggregate_failures do
122
+ expect(subject.dig!(:k, 0)).to eq(1)
123
+ expect(subject.dig!(:k, 1)).to eq(2)
124
+ expect(subject.dig!(:j, 0, :a)).to eq(1)
125
+ expect(subject.dig!(:j, 1, :b)).to eq(2)
126
+ end
127
+
128
+ it 'raises exception when key not found', :aggregate_failures do
129
+ expect { subject.dig!('c', 'f') }.to raise_error(KeyError, "Configuration key 'c.f' is not set")
130
+ expect { subject.dig!('d') }.to raise_error(KeyError, "Configuration key 'd' is not set")
131
+ expect { subject.dig!(:j, 1, :c) }.to raise_error(KeyError, "Configuration key 'j.1.c' is not set")
132
+ end
133
+ end
134
+
135
+ describe '#fetch' do
136
+ it 'retrieves members using string keys', :aggregate_failures do
137
+ expect(subject.fetch('a')).to eq(1)
138
+ expect(subject.fetch('b')).to eq(2)
139
+ end
140
+
141
+ it 'retrieves members using symbol keys', :aggregate_failures do
142
+ expect(subject.fetch(:a)).to eq(1)
143
+ expect(subject.fetch(:b)).to eq(2)
144
+ end
145
+
146
+ it 'raise error when key is not present and no block is given', :aggregate_failures do
147
+ expect { subject.fetch('d') }.to raise_error(KeyError, "Configuration key 'd' is not set")
148
+ expect { subject.fetch(:e) }.to raise_error(KeyError, "Configuration key 'e' is not set")
149
+ end
150
+
151
+ it 'calls block when it is given and key is not present', :aggregate_failures do
152
+ expect(subject.fetch(:e, 1)).to eq(1)
153
+ expect(subject.fetch('f', 2)).to eq(2)
154
+ end
155
+ end
156
+
157
+ describe '#source' do
158
+ it 'returns the source', :aggregate_failures do
159
+ expect(subject.source(:a)).to eq('env a')
160
+ expect(subject.source(:b)).to eq('env b')
161
+ expect(subject.source(:c)).to eq('env c')
162
+ expect(subject.source(:c, :d)).to eq('env c.d')
163
+ expect(subject.source(:c, :e)).to eq('env c.e')
164
+ expect(subject.source(:k, 0)).to eq('env k.0')
165
+ expect(subject.source(:j, 0)).to eq('env j.0')
166
+ expect(subject.source(:j, 0, :a)).to eq('env j.0.a')
167
+ end
168
+
169
+ context 'when merging 2 sources' do
170
+ let(:source1) do
171
+ {
172
+ a: 1,
173
+ b: 2,
174
+ c: {
175
+ d: 1,
176
+ e: 2
177
+ },
178
+ k: [1, 2, 3],
179
+ j: [{ a: 1 }, { b: 2 }]
180
+ }
181
+ end
182
+ let(:source2) do
183
+ {
184
+ a: 1,
185
+ g: 3,
186
+ c: {
187
+ d: 2,
188
+ f: 3
189
+ },
190
+ k: [:__append, 4, 5],
191
+ j: [:__append, { x: 1 }, { y: 2 }]
192
+ }
193
+ end
194
+ let(:options1) { described_class.new(source1, source: 'env1') }
195
+ let(:options2) { described_class.new(source2, source: 'env2') }
196
+ subject { options1.deep_merge(options2) }
197
+
198
+ it 'returns the source', :aggregate_failures do
199
+ expect(subject.source(:a)).to eq('env1 a')
200
+ expect(subject.source(:b)).to eq('env1 b')
201
+ expect(subject.source(:c)).to eq('env1 c')
202
+ expect(subject.source(:g)).to eq('env2 g')
203
+ expect(subject.source(:c, :d)).to eq('env1 c.d')
204
+ expect(subject.source(:c, :e)).to eq('env1 c.e')
205
+ expect(subject.source(:k, 4)).to eq('env2 k.2')
206
+ expect(subject.source(:j, 0, :a)).to eq('env1 j.0.a')
207
+ expect(subject.source(:j, 3, :y)).to eq('env2 j.2.y')
208
+ end
209
+ end
210
+ end
211
+ end
@@ -0,0 +1,24 @@
1
+ default:
2
+ nested:
3
+ a: 1
4
+ b: 2
5
+ array:
6
+ - a
7
+ - b
8
+ - x
9
+ array2:
10
+ - a:
11
+ d: 1
12
+ e: 2
13
+ b: 2
14
+ - b: 1
15
+ c: 3
16
+ - x: 4
17
+ y: 5
18
+
19
+ test:
20
+ quox: baz
21
+ envir: "<%= ENV['APP_EXAMPLE'] %>"
22
+ nested:
23
+ a: 3
24
+ c: 4
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe BlueprintConfig::Configuration do
4
+ let(:key_set1) do
5
+ {
6
+ a: 1,
7
+ b: 2
8
+ }
9
+ end
10
+
11
+ let(:key_set2) do
12
+ {
13
+ a: 3,
14
+ c: 4,
15
+ e: '<%= AppConfig.a %>'
16
+ }
17
+ end
18
+
19
+ let(:backend) { double('backend', load_keys: key_set1, source: 'backend', fresh?: true) }
20
+ let(:other_backend) { double('other backend', load_keys: key_set2, source: 'other_backend', fresh?: true) }
21
+ let(:config) { described_class.instance }
22
+
23
+ before do
24
+ stub_const('AppConfig', config)
25
+ config.init do |backends|
26
+ backends.push(:one, backend)
27
+ backends.push(:other, other_backend)
28
+ end
29
+ end
30
+
31
+ describe 'getting values as method calls' do
32
+ it 'returns the value of a given key' do
33
+ expect(config.a).to eq(3)
34
+ expect(config.c).to eq(4)
35
+ expect(config.e).to eq('3')
36
+ end
37
+ it 'checks backend freshness' do
38
+ expect(backend).to receive(:fresh?).and_return(true)
39
+ expect(config.c).to eq(4)
40
+ end
41
+ it 'reloads when backend is stale' do
42
+ expect(backend).to receive(:fresh?).and_return(false)
43
+ expect(config).to receive(:reload!).and_call_original
44
+ expect(config.c).to eq(4)
45
+ end
46
+ end
47
+
48
+ describe 'getting values with []' do
49
+ it 'returns the value of a given key' do
50
+ expect(config[:a]).to eq(3)
51
+ expect(config[:c]).to eq(4)
52
+ expect(config[:e]).to eq('3')
53
+ end
54
+ it 'checks backend freshness' do
55
+ expect(backend).to receive(:fresh?).and_return(true)
56
+ expect(config[:c]).to eq(4)
57
+ end
58
+ it 'reloads when backend is stale' do
59
+ expect(backend).to receive(:fresh?).and_return(false)
60
+ expect(config).to receive(:reload!).and_call_original
61
+ expect(config[:c]).to eq(4)
62
+ end
63
+ end
64
+
65
+ describe 'getting values with dig' do
66
+ it 'returns the value of a given key' do
67
+ expect(config[:a]).to eq(3)
68
+ expect(config[:c]).to eq(4)
69
+ expect(config[:e]).to eq('3')
70
+ end
71
+ it 'checks backend freshness' do
72
+ expect(backend).to receive(:fresh?).and_return(true)
73
+ expect(config[:c]).to eq(4)
74
+ end
75
+ it 'reloads when backend is stale' do
76
+ expect(backend).to receive(:fresh?).and_return(false)
77
+ expect(config).to receive(:reload!).and_call_original
78
+ expect(config[:c]).to eq(4)
79
+ end
80
+ end
81
+
82
+ describe 'getting values with dig!' do
83
+ it 'returns the value of a given key' do
84
+ expect(config.dig!(:a)).to eq(3)
85
+ expect(config.dig!(:c)).to eq(4)
86
+ expect(config.dig!(:e)).to eq('3')
87
+ end
88
+ it 'checks backend freshness' do
89
+ expect(backend).to receive(:fresh?).and_return(true)
90
+ expect(config.dig!(:c)).to eq(4)
91
+ end
92
+ it 'reloads when backend is stale' do
93
+ expect(backend).to receive(:fresh?).and_return(false)
94
+ expect(config).to receive(:reload!).and_call_original
95
+ expect(config.dig!(:c)).to eq(4)
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'blueprint_config'
4
+
5
+ BlueprintConfig.root = File.dirname(__FILE__)
6
+ BlueprintConfig.env = 'test'
7
+
8
+ RSpec.configure do |config|
9
+ config.expect_with :rspec do |c|
10
+ c.syntax = %i[expect should]
11
+ end
12
+
13
+ config.mock_with :rspec do |c|
14
+ c.syntax = %i[expect should]
15
+ end
16
+ end
metadata ADDED
@@ -0,0 +1,163 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: blueprint_config
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Vladimir Elchinov
8
+ - Rails Blueprint
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2024-01-08 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activerecord
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rake
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: redis
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: rspec
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: sqlite3
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ description: Flexible configuration for Ruby/Rails applications with a variety of
85
+ backends
86
+ email:
87
+ - elik@elik.ru
88
+ - info@railsblueprint.com
89
+ executables: []
90
+ extensions: []
91
+ extra_rdoc_files: []
92
+ files:
93
+ - ".gitignore"
94
+ - ".idea/.gitignore"
95
+ - ".idea/blue_config.iml"
96
+ - ".idea/misc.xml"
97
+ - ".idea/modules.xml"
98
+ - ".idea/vcs.xml"
99
+ - ".rspec"
100
+ - ".ruby-version"
101
+ - Gemfile
102
+ - LICENSE.txt
103
+ - README.md
104
+ - Rakefile
105
+ - blueprint_config.gemspec
106
+ - lib/blueprint_config.rb
107
+ - lib/blueprint_config/backend/active_record.rb
108
+ - lib/blueprint_config/backend/base.rb
109
+ - lib/blueprint_config/backend/credentials.rb
110
+ - lib/blueprint_config/backend/env.rb
111
+ - lib/blueprint_config/backend/yaml.rb
112
+ - lib/blueprint_config/backend_collection.rb
113
+ - lib/blueprint_config/configuration.rb
114
+ - lib/blueprint_config/options_array.rb
115
+ - lib/blueprint_config/options_hash.rb
116
+ - lib/blueprint_config/setting.rb
117
+ - lib/blueprint_config/version.rb
118
+ - lib/blueprint_config/yaml.rb
119
+ - lib/generators/blueprint_config/install/USAGE
120
+ - lib/generators/blueprint_config/install/install_generator.rb
121
+ - lib/generators/blueprint_config/install/templates/migration.rb.erb
122
+ - spec/backend_collection_spec.rb
123
+ - spec/blueprint_config/backend/active_record_spec.rb
124
+ - spec/blueprint_config/backend/env_spec.rb
125
+ - spec/blueprint_config/backend/yaml_spec.rb
126
+ - spec/blueprint_config/options_array_spec.rb
127
+ - spec/blueprint_config/options_hash_spec.rb
128
+ - spec/config/app.yml
129
+ - spec/configuration_spec.rb
130
+ - spec/spec_helper.rb
131
+ homepage: https://github.com/railsblueprint/blueprint_config
132
+ licenses:
133
+ - MIT
134
+ metadata: {}
135
+ post_install_message:
136
+ rdoc_options: []
137
+ require_paths:
138
+ - lib
139
+ required_ruby_version: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - "~>"
142
+ - !ruby/object:Gem::Version
143
+ version: '3.0'
144
+ required_rubygems_version: !ruby/object:Gem::Requirement
145
+ requirements:
146
+ - - ">="
147
+ - !ruby/object:Gem::Version
148
+ version: '0'
149
+ requirements: []
150
+ rubygems_version: 3.4.22
151
+ signing_key:
152
+ specification_version: 4
153
+ summary: Congifure Ruby apps
154
+ test_files:
155
+ - spec/backend_collection_spec.rb
156
+ - spec/blueprint_config/backend/active_record_spec.rb
157
+ - spec/blueprint_config/backend/env_spec.rb
158
+ - spec/blueprint_config/backend/yaml_spec.rb
159
+ - spec/blueprint_config/options_array_spec.rb
160
+ - spec/blueprint_config/options_hash_spec.rb
161
+ - spec/config/app.yml
162
+ - spec/configuration_spec.rb
163
+ - spec/spec_helper.rb