yaml_settings 1.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 248f78a2595723d1f64b57406b7bed078831232b
4
+ data.tar.gz: 302fa7f374b773c56fa3dbc93655711f3e6b3dab
5
+ SHA512:
6
+ metadata.gz: a3d3f8bcb4964b607d765369f31ba74781e39d851396a69bbb91d3a4718510156f713cc6824b0d709e173f062ba3eaec21b134d1561fd1156792d5c8b910a36e
7
+ data.tar.gz: ef37138b7b107afaed5f377382bd0a314cddba81d7e8770987afdd5278bc34f7e0c273ad99c5fd65af9c84b910ba221652c234e770f2456cd9ab635ce90d5e26
@@ -0,0 +1,11 @@
1
+ --- !ruby/object:RDoc::Options
2
+ charset: UTF-8
3
+ encoding: UTF-8
4
+ static_path: []
5
+ rdoc_include:
6
+ - "."
7
+ exclude:
8
+ line_numbers: false
9
+ main_page: README.rdoc
10
+ markup: rdoc
11
+ title: YAMLSettings Ruby Gem - Load and merge app settings from YAML files
@@ -0,0 +1,154 @@
1
+ = YAML Settings
2
+
3
+ Load and merge application settings from YAML files.
4
+
5
+ At load time, settings are merged in two stages. First, all YAML data are
6
+ recursively merged in reverse file order. Settings in succeeding files override
7
+ all duplicate settings in preceding files. Second, the user selected
8
+ settings—specified by key (e.g., environment key)—are recursively merged with
9
+ the default settings.
10
+
11
+ This class can load multiple settings files, which provides a few benefits:
12
+
13
+ 1. Confidential settings can be stored separately and securely from
14
+ non-confidential settings; for example, in a public repository.
15
+
16
+ 2. Settings for each application component or service (e.g., database, payment
17
+ gateway, logger, CDN) can be stored in their respective files.
18
+
19
+ 3. Shared or system-wide settings can be merged with application settings.
20
+
21
+
22
+ == Settings File Examples
23
+
24
+ The following are settings files, defined using YAML[http://yaml.org], which
25
+ typically use the +.yml+ or +.yaml+ file extension. For information on how to
26
+ craft YAML, see the spec[http://yaml.org/spec/].
27
+
28
+ === Absolute minimal settings
29
+
30
+ default:
31
+
32
+ Above is the *mandatory* +default+ stanza, which must be present in at least one
33
+ of the YAML settings files, even if it is empty. This isn't very useful, so lets
34
+ add a couple of default settings.
35
+
36
+ default:
37
+ setting_1: on
38
+ setting_2: off
39
+
40
+
41
+ === Database settings
42
+
43
+ Here we have settings that specify the database name, user, host, and password
44
+ file. There are three additional top-level stanzas: +development+, +production+,
45
+ and +test+. These stanzas can be defined for any reason and have any name, but
46
+ typically represent the runtime environment or mode of the application. Zero or
47
+ more non-default top-level stanzas can be defined.
48
+
49
+ # database.yaml
50
+ default:
51
+ db:
52
+ host: db.example.com
53
+ user: dbusr
54
+ pass: config/db-access
55
+
56
+ development:
57
+ db:
58
+ name: myapp_dev
59
+
60
+ production:
61
+ db:
62
+ name: myapp
63
+ pass: /var/www/sites/myapp/db-access
64
+
65
+ test:
66
+ db:
67
+ name: myapp_test
68
+
69
+ With these settings, the +default+ will always provide the database +host+ and
70
+ +user+ because it is not overridden in any other stanza. However, the database
71
+ +name+ is not specified in +default+ because it is set in each environment. In
72
+ +production+, the database password file is unique—and secure of course—thus
73
+ overrides +default+.
74
+
75
+
76
+ == Usage Examples
77
+
78
+ <em>First things first!</em>
79
+
80
+ require 'yaml_settings'
81
+
82
+ === Load database settings
83
+
84
+ Load +production+ using the database settings above. The +production+ settings
85
+ are merged into +default+.
86
+
87
+ settings = YAMLSettings.new('database.yaml', :production)
88
+ settings.db.host # => "db.example.com"
89
+ settings.db.user # => "dbusr"
90
+ settings.db.name # => "myapp"
91
+ settings.db.pass # => "/var/www/sites/myapp/db-access"
92
+
93
+ The settings are accessed using methods. The +db+ setting is actually a Hash and
94
+ can also be accessed as such.
95
+
96
+ settings.db['host'] # => "db.example.com"
97
+
98
+ The difference is that method access raises an error if a setting is nonexistent.
99
+
100
+ settings.db.mia # KeyError: key not found: "mia"
101
+ settings.db['mia'] # => nil
102
+
103
+ Method access is only available for string and symbol keys of Hash settings.
104
+
105
+ === Load multiple settings files
106
+
107
+ It may be helpful to store settings for each application component separately.
108
+ Or perhaps, settings are in a shared location. Here's how to initialize for such
109
+ a situation:
110
+
111
+ settings = YAMLSettings.new '/etc/app-defaults.yml', # system wide
112
+ '/etc/payment-gateway.yml', # system wide
113
+ '/var/www/share/config/cdn.yml', # common for sites
114
+ 'config/app.yml', # app specific
115
+ 'config/database.yml', # app specific
116
+ ENV['APP_MODE']
117
+
118
+ The +settings+ variable above is a compilation of four merges. First,
119
+ _config/database.yml_ will merge with and override _config/app.yml_; the result
120
+ will merge with and override _cdn.yml_; and so on. Therefore, specify files with
121
+ more generic settings first.
122
+
123
+
124
+ == Links
125
+
126
+ Homepage :: https://ecentryx.com/gems/yaml_settings
127
+ Ruby Gem :: https://rubygems.org/gems/yaml_settings
128
+ Source Code :: https://bitbucket.org/pachl/yaml_settings/src
129
+ Bug Tracker :: https://bitbucket.org/pachl/yaml_settings/issues
130
+
131
+
132
+ == History
133
+
134
+ 1. 2017-06-30, v1.0.6
135
+ * First public release
136
+
137
+
138
+ == License
139
+
140
+ ({ISC License}[https://opensource.org/licenses/ISC])
141
+
142
+ Copyright (c) 2013-2017, Clint Pachl <pachl@ecentryx.com>
143
+
144
+ Permission to use, copy, modify, and/or distribute this software for any purpose
145
+ with or without fee is hereby granted, provided that the above copyright notice
146
+ and this permission notice appear in all copies.
147
+
148
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
149
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
150
+ FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
151
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
152
+ OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
153
+ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
154
+ THIS SOFTWARE.
@@ -0,0 +1,22 @@
1
+ GEM_NAME = File.basename(Dir['*.gemspec'][0], '.*')
2
+
3
+ desc 'Build gem'
4
+ task :gem do
5
+ system "gem build #{GEM_NAME}.gemspec"
6
+ end
7
+
8
+ desc 'Publish docs'
9
+ task :pub do
10
+ dir = ENV.fetch('public_gem_dir') + GEM_NAME
11
+ host = ENV.fetch('public_gem_host')
12
+
13
+ if system 'rdoc lib README.rdoc'
14
+ `cd ./doc && pax -w . | ssh #{host} 'cd #{dir} && rm -rf * && pax -r'`
15
+ `rm -r ./doc;`
16
+ end
17
+ end
18
+
19
+ desc 'Run tests'
20
+ task :test do
21
+ system 'bacon -a'
22
+ end
@@ -0,0 +1,59 @@
1
+ require 'delegate'
2
+ require 'yaml'
3
+
4
+ class YAMLSettings < DelegateClass(Hash)
5
+
6
+ VERSION = '1.0.6'
7
+
8
+ module AttrReader # :nodoc:
9
+ def method_missing(setting)
10
+ has_key?(setting) ? fetch(setting) : fetch(setting.to_s) # raises KeyError
11
+ end
12
+ private :method_missing
13
+ end
14
+
15
+ #
16
+ # Settings are merged in two stages. First, all +filenames+ are recursively
17
+ # merged in reverse order. Settings in succeeding +filenames+ overwrite all
18
+ # duplicate settings in preceding +filenames+. Second, settings specified by
19
+ # +key+ are then recursively merged with the _default_ settings.
20
+ #
21
+ # +filenames+:: one or more YAML data files
22
+ # +key+:: selects the top-level stanza from +filenames+ to be merged
23
+ # with the _default_ stanza
24
+ #
25
+ def initialize(*filenames, key)
26
+ all_settings = filenames.collect {|f| YAML.load_file(f) }
27
+ settings = all_settings.reduce {|i, j| deep_merge(i, j) }
28
+ @settings = deep_merge(settings.fetch('default'),
29
+ settings.fetch(key.to_s))
30
+ @settings.extend(AttrReader)
31
+ propagate_attr_reader(@settings)
32
+ super(@settings)
33
+ end
34
+
35
+ def inspect() @settings.inspect end
36
+ alias :to_s :inspect
37
+
38
+ private
39
+
40
+ def method_missing(setting, *args, &blk)
41
+ super rescue @settings.send(setting)
42
+ end
43
+
44
+ def deep_merge(h1, h2)
45
+ h1.merge!(h2) do |key, v1, v2|
46
+ v1.is_a?(Hash) && v2.is_a?(Hash) ? deep_merge(v1, v2) : v2
47
+ end
48
+ end
49
+
50
+ def propagate_attr_reader(settings)
51
+ settings.each_value do |setting_value|
52
+ if setting_value.is_a? Hash
53
+ setting_value.extend(AttrReader)
54
+ propagate_attr_reader(setting_value)
55
+ end
56
+ end
57
+ end
58
+
59
+ end
@@ -0,0 +1,79 @@
1
+ # NOTE: Settings with a value of 'default overriden' should never be accessible.
2
+ default:
3
+ a: 'default overriden'
4
+ c:
5
+ a:
6
+ a: 'default overriden'
7
+ b: 'default c.a.b'
8
+ b: 'default c.b'
9
+ c: 'default overriden'
10
+ d:
11
+ a: 'default d.a'
12
+ e:
13
+ a:
14
+ a: 'default overriden'
15
+ b: 'default overriden'
16
+ b:
17
+ a: 'default e.b.a'
18
+ b: 'default overriden'
19
+ f:
20
+ - 'default 0'
21
+ - 'default 1'
22
+ g:
23
+ - 'default overriden'
24
+ - 'default overriden'
25
+ - 'default overriden'
26
+ :h: 'default h'
27
+ i:
28
+ a: 'default i.a'
29
+ j:
30
+ a:
31
+ a: 'default j.a.a'
32
+ k:
33
+ a: 'default overriden'
34
+ b: 'default overriden'
35
+ c: 'default overriden'
36
+ d: 'default k.d'
37
+ l:
38
+ a: 'default overriden'
39
+ b: 'default overriden'
40
+ m: 'default m'
41
+
42
+ test:
43
+ a: 'test a'
44
+ b:
45
+ a: 'test b.a'
46
+ b: 'test b.b'
47
+ c:
48
+ a:
49
+ a: 'test c.a.a'
50
+ c: 'test c.c'
51
+ d:
52
+ b: 'test d.b'
53
+ e:
54
+ a:
55
+ a: 'test e.a.a'
56
+ b: 'test e.a.b'
57
+ b:
58
+ b: 'test e.b.b'
59
+ g:
60
+ - 'test 0'
61
+ - 'test 1'
62
+ k:
63
+ a: 'test k.a'
64
+ b: 'test k.b'
65
+ c: 'test k.c'
66
+ e: 'test k.e'
67
+ l: 'test l'
68
+ m:
69
+ a: 'test m.a'
70
+
71
+ development:
72
+ a: 'development a'
73
+
74
+ production:
75
+ a: 'production a'
76
+ k:
77
+ a: 'production k.a'
78
+ b: 'production overriden'
79
+
@@ -0,0 +1,3 @@
1
+ # Missing "default" stanza; no bueno!
2
+ development:
3
+ setting_1: 'setting 1'
@@ -0,0 +1,3 @@
1
+ # For simple configurations, allow just the "default" stanza.
2
+ default:
3
+ setting_1: 'setting 1'
@@ -0,0 +1,18 @@
1
+ default:
2
+ db:
3
+ host: db.example.com
4
+ user: dbusr
5
+ pass: config/db-access
6
+
7
+ development:
8
+ db:
9
+ name: myapp_dev
10
+
11
+ production:
12
+ db:
13
+ name: myapp
14
+ pass: /var/www/sites/myapp/db-access
15
+
16
+ test:
17
+ db:
18
+ name: myapp_test
@@ -0,0 +1,6 @@
1
+ # Confidential settings to be securely stored.
2
+ production:
3
+ a: 'production a [private]'
4
+ k:
5
+ b: 'production k.b [private]'
6
+ c: 'production k.c [private]'
@@ -0,0 +1,6 @@
1
+ # Symbols as environment keys are not allowed.
2
+ :default:
3
+ setting_1: 'setting 1'
4
+
5
+ :development:
6
+ setting_2: 'setting 2'
@@ -0,0 +1,13 @@
1
+ describe 'README Examples' do
2
+
3
+ should 'load database settings' do
4
+ yaml = File.join(File.dirname(__FILE__), "fixtures", "example_database.yml")
5
+
6
+ settings = YAMLSettings.new(yaml, :production)
7
+ settings.db.host.should == "db.example.com"
8
+ settings.db.user.should == "dbusr"
9
+ settings.db.name.should == "myapp"
10
+ settings.db.pass.should == "/var/www/sites/myapp/db-access"
11
+ end
12
+
13
+ end
@@ -0,0 +1,167 @@
1
+ require 'yaml_settings'
2
+
3
+ describe YAMLSettings do
4
+
5
+ def fixture name
6
+ File.join(File.dirname(__FILE__), "fixtures", "#{name}.yml")
7
+ end
8
+
9
+ ys = YAMLSettings.new(fixture(:default), :test)
10
+
11
+ should 'load and merge multiple YAML files' do
12
+ p = YAMLSettings.new(
13
+ fixture(:default),
14
+ fixture(:private),
15
+ :production
16
+ )
17
+ p.a. should == 'production a [private]'
18
+ p.k.a.should == 'production k.a'
19
+ p.k.b.should == 'production k.b [private]'
20
+ p.k.c.should == 'production k.c [private]'
21
+ p.k.d.should == 'default k.d'
22
+ end
23
+
24
+ should 'allow either a string or symbol for environment parameter' do
25
+ str = YAMLSettings.new(fixture(:default), 'development')
26
+ sym = YAMLSettings.new(fixture(:default), :development)
27
+ str.a.should == 'development a'
28
+ sym.a.should == 'development a'
29
+ end
30
+
31
+ should 'allow only string environment keys in YAML files' do
32
+ should.raise(KeyError) {
33
+ YAMLSettings.new(fixture(:symbol_keys), :development)
34
+ }.message.should.equal 'key not found: "default"'
35
+ end
36
+
37
+ should 'allow just a "default" stanza in YAML file' do
38
+ default = YAMLSettings.new(fixture(:default_only), :default)
39
+ default.setting_1.should.equal 'setting 1'
40
+ end
41
+
42
+ should 'raise if "default" stanza does not exist' do
43
+ should.raise(KeyError) {
44
+ YAMLSettings.new(fixture(:default_missing), :development)
45
+ }.message.should.equal 'key not found: "default"'
46
+ end
47
+
48
+ should 'raise if specified environment does not exist' do
49
+ should.raise(KeyError) { # single file
50
+ YAMLSettings.new(fixture(:default), "nonexistent")
51
+ }.message.should.equal 'key not found: "nonexistent"'
52
+
53
+ should.raise(KeyError) { # multiple files
54
+ YAMLSettings.new(fixture(:default_only),
55
+ fixture(:default),
56
+ fixture(:private),
57
+ "nonexistent")
58
+ }.message.should.equal 'key not found: "nonexistent"'
59
+ end
60
+
61
+ should 'delegate to a Hash object' do
62
+ [:hash, :key, :keys, :each_value, :merge, :rehash].each do |hash_method|
63
+ ys.public_methods.should.include? hash_method
64
+ end
65
+ ys.__getobj__.class.should.equal Hash
66
+ end
67
+
68
+ should 'act like a Hash' do
69
+ ys.keys.should == # "b" not in default
70
+ ["a", "c", "d", "e", "f", "g", :h, "i", "j", "k", "l", "m", "b"]
71
+ ys.values.count.should == 13
72
+ ys['a'].should == 'test a'
73
+ end
74
+
75
+ should 'allow method call for symbol keys' do
76
+ ys.h.should == ys[:h]
77
+ end
78
+
79
+ should 'raise when accessing nonexistent settings via method call' do
80
+ [ -> { ys. mia_setting }, # TOP level
81
+ -> { ys.b. mia_setting }, # 2nd level
82
+ -> { ys.c.a.mia_setting }, # 3rd level
83
+ -> { ys.i. mia_setting }, # 2nd level from default
84
+ -> { ys.j.a.mia_setting } # 3nd level from default
85
+ ].each do |setting|
86
+ should.raise(KeyError) { setting.call }.
87
+ message.should.equal 'key not found: "mia_setting"'
88
+ end
89
+ end
90
+
91
+ should 'not raise when accessing nonexistent settings via hash bracket' do
92
+ [ -> { ys['mia_setting'] },
93
+ -> { ys.d['mia_setting'] }
94
+ ].each do |setting|
95
+ should.not.raise { setting.call }
96
+ setting.call.should.equal nil
97
+ end
98
+ end
99
+
100
+ should 'return non-default setting from each environment' do
101
+ %w(development production test).each do |env|
102
+ YAMLSettings.new(fixture(:default), env).a.should == env+' a'
103
+ end
104
+ end
105
+
106
+ should 'return settings using hash bracket or method call at any level' do
107
+ i = 'test e.a.b'
108
+ ys['e']['a']['b'].should == i # 000
109
+ ys['e']['a'] .b .should == i # 001
110
+ ys['e'] .a[ 'b'].should == i # 010
111
+ ys['e'] .a .b .should == i # 011
112
+ ys .e[ 'a']['b'].should == i # 100
113
+ ys .e[ 'a'] .b .should == i # 101
114
+ ys .e .a[ 'b'].should == i # 110
115
+ ys .e .a .b .should == i # 111
116
+ end
117
+
118
+ should 'return default string settings at multiple levels' do
119
+ ys.c.a.b.should == 'default c.a.b'
120
+ ys.c.b. should == 'default c.b'
121
+ ys.d.a. should == 'default d.a'
122
+ ys.e.b.a.should == 'default e.b.a'
123
+ end
124
+
125
+ should 'return non-defualt string settings at multiple levels' do
126
+ ys.a. should == 'test a'
127
+ ys.b.a. should == 'test b.a'
128
+ ys.b.b. should == 'test b.b'
129
+ ys.c.a.a.should == 'test c.a.a'
130
+ ys.c.c. should == 'test c.c'
131
+ ys.d.b. should == 'test d.b'
132
+ ys.e.a.a.should == 'test e.a.a'
133
+ ys.e.a.b.should == 'test e.a.b'
134
+ ys.e.b.b.should == 'test e.b.b'
135
+ end
136
+
137
+ should 'only override hash values for duplicate keys' do
138
+ ys.k.a.should == 'test k.a'
139
+ ys.k.b.should == 'test k.b'
140
+ ys.k.c.should == 'test k.c'
141
+ ys.k.d.should == 'default k.d'
142
+ ys.k.e.should == 'test k.e'
143
+ end
144
+
145
+ should 'override default hash with string value' do
146
+ ys.l.should == 'test l'
147
+ should.raise(NoMethodError) { ys.l.a } # no access to default hash
148
+ end
149
+
150
+ should 'override default string value with hash' do
151
+ ys.m.class.should.equal Hash
152
+ ys.m.keys.count.should == 1
153
+ end
154
+
155
+ should 'return default array setting' do
156
+ ys.f[0].should == 'default 0'
157
+ ys.f[1].should == 'default 1'
158
+ end
159
+
160
+ should 'return non-default array setting' do
161
+ ys.g[0].should == 'test 0'
162
+ ys.g[1].should == 'test 1'
163
+ ys.g[2].should.be.nil # unlike hash, duplicate indexes not preserved
164
+ ys.g.size.should == 2
165
+ end
166
+
167
+ end
@@ -0,0 +1,29 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'yaml_settings'
3
+ s.version = File.read('lib/yaml_settings.rb')[/VERSION = '(.*)'/, 1]
4
+ s.author = 'Clint Pachl'
5
+ s.email = 'pachl@ecentryx.com'
6
+ s.homepage = 'https://ecentryx.com/gems/yaml_settings'
7
+ s.license = 'ISC'
8
+ s.summary = 'Load and merge application settings from YAML files'
9
+ s.description = <<-EOS
10
+ YAMLSettings loads and recursively merges settings from one or more YAML data
11
+ files. A settings group—specified by key (e.g., environment variable)—is merged
12
+ with any default settings to create a coherent hash of settings.
13
+ EOS
14
+ s.files = Dir[
15
+ 'Rakefile',
16
+ 'README*',
17
+ '*.gemspec',
18
+ 'lib/*.rb',
19
+ 'spec/**/*',
20
+ '.rdoc_options'
21
+ ]
22
+ s.extra_rdoc_files = ['README.rdoc']
23
+ s.rdoc_options = [
24
+ '--title', "YAMLSettings Ruby Gem: #{s.summary}",
25
+ '--main', 'README.rdoc'
26
+ ]
27
+ s.required_ruby_version = '>= 2.2'
28
+ s.add_development_dependency 'bacon', '~> 1.2'
29
+ end
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: yaml_settings
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.6
5
+ platform: ruby
6
+ authors:
7
+ - Clint Pachl
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-06-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bacon
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.2'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.2'
27
+ description: |
28
+ YAMLSettings loads and recursively merges settings from one or more YAML data
29
+ files. A settings group—specified by key (e.g., environment variable)—is merged
30
+ with any default settings to create a coherent hash of settings.
31
+ email: pachl@ecentryx.com
32
+ executables: []
33
+ extensions: []
34
+ extra_rdoc_files:
35
+ - README.rdoc
36
+ files:
37
+ - ".rdoc_options"
38
+ - README.rdoc
39
+ - Rakefile
40
+ - lib/yaml_settings.rb
41
+ - spec/fixtures/default.yml
42
+ - spec/fixtures/default_missing.yml
43
+ - spec/fixtures/default_only.yml
44
+ - spec/fixtures/example_database.yml
45
+ - spec/fixtures/private.yml
46
+ - spec/fixtures/symbol_keys.yml
47
+ - spec/spec_readme_examples.rb
48
+ - spec/spec_yaml_settings.rb
49
+ - yaml_settings.gemspec
50
+ homepage: https://ecentryx.com/gems/yaml_settings
51
+ licenses:
52
+ - ISC
53
+ metadata: {}
54
+ post_install_message:
55
+ rdoc_options:
56
+ - "--title"
57
+ - 'YAMLSettings Ruby Gem: Load and merge application settings from YAML files'
58
+ - "--main"
59
+ - README.rdoc
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: '2.2'
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ requirements: []
73
+ rubyforge_project:
74
+ rubygems_version: 2.6.12
75
+ signing_key:
76
+ specification_version: 4
77
+ summary: Load and merge application settings from YAML files
78
+ test_files: []