config 2.2.3 → 5.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2212e68e8bb8e15f821b9420db10ec3111edcaa43bffe5450ae850d5228b3107
4
- data.tar.gz: de9c513f5a6450a95e113071adf79c3d3b3e2f3485a018e14ab72241a2f419e0
3
+ metadata.gz: e40351432c70fbb2587ca9b4c8e6b200b1f971b88e4bae6ceb06829fafa5520e
4
+ data.tar.gz: 1fb0585b03fd3219922e018ac9b87f8035a44235b0a3cd7566cad2e65c50983d
5
5
  SHA512:
6
- metadata.gz: ae72b6c10869bbca57d7c476e5ba7b48637b6c94c083176b2c7321710bd4daebe5f41c03d3daf69157dd3f599f63f11d74e19141e98716ae3ef20c8c33469ba3
7
- data.tar.gz: 07e79c9a667587218a3370c03e912c113795fa00a9f50350065834c91b9d858e03ee1447da078e6ec5af19c32faa5317f3a94b071478d4b96397317504891ac7
6
+ metadata.gz: c7af987c69d0859f237911f8ff070c2b986b6ac98379245549cfbf69b902c239d315576dbf8979b4847dafd756563843a2b6b90d1b03bdff7abb7440709b0992
7
+ data.tar.gz: cd5277068a5d253002abed87cd0b6ff02c6b1ff35c558d449f12606f799b08e5fa9a0e01ff386bb087bb8c3395577e195e41d9d65a202e48e0f9bfc3209a5622
data/CHANGELOG.md CHANGED
@@ -1,8 +1,111 @@
1
1
  # Changelog
2
2
 
3
- ## Unreleased
3
+ ## 5.5.2
4
4
 
5
- ...
5
+ * Fix warning: ostruct was loaded from the standard library with Ruby 3.3.5 and 3.4+ ([#363](https://github.com/rubyconfig/config/pull/363))
6
+
7
+ ## 5.5.1
8
+
9
+ ### Documentation
10
+
11
+ * Fix funding_url to funding_uri in gemspec ([#361](https://github.com/rubyconfig/config/pull/361))
12
+
13
+ ## 5.5.0
14
+
15
+ ### New features
16
+
17
+ * Allow arrays to be passed through env variables ([#354](https://github.com/rubyconfig/config/pull/354))
18
+
19
+ ### Documentation
20
+
21
+ * Use funding_url rather than post_install_message ([#360](https://github.com/rubyconfig/config/pull/360))
22
+ * Fix typos in the tests and documentation ([#359](https://github.com/rubyconfig/config/pull/359))
23
+
24
+ ## 5.4.0
25
+
26
+ ### New features
27
+
28
+ * Add configuration option `environment` to override the use of `Rails.env` ([#356](https://github.com/rubyconfig/config/pull/356))
29
+
30
+ ## 5.3.0
31
+
32
+ * Remove `dry-validation` from dependencies ([#333](https://github.com/rubyconfig/config/pull/333))
33
+
34
+ ## 5.2.0
35
+
36
+ ### New features
37
+
38
+ * Allow to use custom filename && directory name to store configs ([#341](https://github.com/rubyconfig/config/pull/341))
39
+
40
+ ### Bug fixes
41
+
42
+ * Prevent name collision with private methods from ancestors ([#351](https://github.com/rubyconfig/config/pull/351))
43
+
44
+ ## 5.1.0
45
+
46
+ * Fix conflicts with Rails 7 active_support methods ([#347](https://github.com/rubyconfig/config/pull/347))
47
+
48
+ ## 5.0.0
49
+
50
+ ### BREAKING CHANGES
51
+
52
+ * No longer load `deep_merge`'s monkey patch for `Hash#deep_merge` and `Hash#deep_merge!` ([#342](https://github.com/rubyconfig/config/pull/342)). If you rely on those methods and are not using Rails / Active Support, you can load the monkey patch via `require 'deep_merge/deep_merge_hash'`. This change fixes Rails 7.x support.
53
+
54
+ ## 4.2.1
55
+
56
+ ### Bug fixes
57
+
58
+ * Address edge case with `table` config param ([#339](https://github.com/rubyconfig/config/pull/339))
59
+
60
+ ## 4.2.0
61
+
62
+ ### Bug fixes
63
+
64
+ * Remove use of method `File.exists?` to fix use in Ruby 3.0 ([#318](https://github.com/rubyconfig/config/pull/318))
65
+
66
+ ## 4.1.0
67
+
68
+ ### Bug fixes
69
+
70
+ * Only load `Railtie` integration if `Rails::Railtie` is defined ([#319](https://github.com/rubyconfig/config/pull/319))
71
+ * Fix indentation warning in Ruby 3.1 ([#322](https://github.com/rubyconfig/config/pull/322))
72
+
73
+ ## 4.0.0
74
+
75
+ ### BREAKING CHANGES
76
+
77
+ * Rails versions `< 5.2` are no longer supported ([#316](https://github.com/rubyconfig/config/pull/316))
78
+ * Ruby versions `< 2.6` are no longer supported ([#316](https://github.com/rubyconfig/config/pull/316))
79
+ * Support `HashSource` and `EnvSource` instances in `Config.load_files` and `Config.load_and_set_settings`. ([#315](https://github.com/rubyconfig/config/pull/315)). There are a few subtle breaking changes:
80
+ * Previously, `Config.load_files` (called from `Config.load_and_set_settings`) would call `.to_s` on each of its arguments. Now, this responsibility is deferred to YAMLSource. In effect, if your application passes String or Pathname objects to `Config.load_files`, no changes are necessary, but if you were somehow relying on the `.to_s` call for some other type of object, you'll now need to call `.to_s` on that object before passing it to `Config`.
81
+ * Before this change, `Config.load_files` would call `uniq` on its argument array. This call has been removed, so duplicate file paths are not removed before further processing. In some cases, this can cause differences in behavior since later config files override the values in earlier ones. In most cases, it's best to ensure that duplicate paths are not passed to `Config.load_files`.
82
+
83
+ ## 3.1.1
84
+
85
+ ### Bug fixes
86
+
87
+ * Allow the use of unsafe YAML parsing features when using psych >= 4 ([#306](https://github.com/railsconfig/config/issues/306))
88
+
89
+ ## 3.1.0
90
+
91
+ ### New features
92
+
93
+ * Evaluating ERB in YAML files can now be disabled with `Config.evaluate_erb_in_yaml = false`. The default value for this option is `true` for backwards-compatibility. ([#303](https://github.com/rubyconfig/config/pull/303))
94
+
95
+ ## 3.0.0
96
+
97
+ ### BREAKING CHANGES
98
+
99
+ * After upgrade behaviour of `to_h` would change and match behaviour of `to_hash`. Check [#217](https://github.com/rubyconfig/config/issues/217#issuecomment-741953382) for more details.
100
+ * `Config::Options#load_env!` and `Config::Options#reload_env!` have been removed. If you need to reload settings after modifying the `ENV` hash, use `Config.reload!` or `Config::Options#reload!` instead.
101
+
102
+ ### Bug fixes
103
+
104
+ * Added alias `to_h` for `to_hash` ([#277](https://github.com/railsconfig/config/issues/277))
105
+
106
+ ### Changes
107
+
108
+ * Add `Config::Sources::EnvSource` for loading settings from flat `Hash`es with `String` keys and `String` values, such as from AWS SecretsManager ([#299](https://github.com/railsconfig/config/pull/299))
6
109
 
7
110
  ## 2.2.3
8
111
 
data/CONTRIBUTING.md CHANGED
@@ -3,7 +3,7 @@
3
3
  Install appraisal
4
4
 
5
5
  ```bash
6
- gem install bundler -v 1.17.3
6
+ gem install bundler
7
7
  gem install appraisal
8
8
  ```
9
9
 
@@ -16,13 +16,19 @@ bundle install
16
16
  Bootstrap
17
17
 
18
18
  ```bash
19
- appraisal install
19
+ bundle exec appraisal install
20
+ ```
21
+
22
+ If you need to create new test app for specific rails version
23
+
24
+ ```bash
25
+ bundle exec appraisal rails-7.0 rails new spec/app/rails_7.0
20
26
  ```
21
27
 
22
28
  Run the test suite:
23
29
 
24
30
  ```bash
25
- appraisal rspec
31
+ bundle exec appraisal rspec
26
32
  ```
27
33
 
28
34
  If you modified any of the documentation files verify their format:
data/README.md CHANGED
@@ -1,9 +1,8 @@
1
1
  # Config
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/config.svg)](http://badge.fury.io/rb/config)
3
+ [![Version](https://img.shields.io/gem/v/config)](https://rubygems.org/gems/config)
4
+ [![Downloads Total](https://img.shields.io/gem/dt/config)](https://rubygems.org/gems/config)
4
5
  [![Tests](https://github.com/rubyconfig/config/workflows/tests/badge.svg)](https://github.com/rubyconfig/config/actions?query=branch%3Amaster)
5
- [![Maintainability](https://api.codeclimate.com/v1/badges/85c206c13dce7de090af/maintainability)](https://codeclimate.com/github/rubyconfig/config/maintainability)
6
- [![Test Coverage](https://api.codeclimate.com/v1/badges/85c206c13dce7de090af/test_coverage)](https://codeclimate.com/github/rubyconfig/config/test_coverage)
7
6
  [![Financial Contributors on Open Collective](https://opencollective.com/rubyconfig/all/badge.svg?label=backers)](https://opencollective.com/rubyconfig)
8
7
 
9
8
  ## Summary
@@ -24,16 +23,18 @@ Config helps you easily manage environment specific settings in an easy and usab
24
23
  Current version supports and is [tested](.github/workflows/tests.yml#L19) for the following interpreters and frameworks:
25
24
 
26
25
  * Interpreters
27
- * [Ruby](https://www.ruby-lang.org) `>= 2.4`
26
+ * [Ruby](https://www.ruby-lang.org) `>= 2.6`
28
27
  * [JRuby](https://www.jruby.org) `>= 9.2`
29
28
  * [TruffleRuby](https://github.com/oracle/truffleruby) `>= 19.3`
30
29
  * Application frameworks
31
- * Rails `>= 4.2`, `5` and `6`
30
+ * Rails `>= 5.2`
32
31
  * Padrino
33
32
  * Sinatra
34
33
 
35
34
  For Ruby `2.0` to `2.3` or Rails `3` to `4.1` use version `1.x` of this gem. For older versions of Rails or Ruby use [AppConfig](http://github.com/fredwu/app_config).
36
35
 
36
+ For Ruby `2.4` or `2.5` or Rails `4.2`, `5.0`, or `5.1` use version `3.x` of this gem.
37
+
37
38
  ## Installing
38
39
 
39
40
  ### Installing on Rails
@@ -52,6 +53,8 @@ which will generate customizable config file `config/initializers/config.rb` and
52
53
 
53
54
  You can now edit them to adjust to your needs.
54
55
 
56
+ > Note: By default, the config environment will match the Rails environment (`Rails.env`). This can be changed by setting `config.environment`.
57
+
55
58
  ### Installing on Padrino
56
59
 
57
60
  Add the gem to your `Gemfile` and run `bundle install` to install it. Then edit `app.rb` and register `Config`
@@ -205,7 +208,9 @@ You may pass a hash to `prepend_source!` as well.
205
208
 
206
209
  ## Embedded Ruby (ERB)
207
210
 
208
- Embedded Ruby is allowed in the configuration files. Consider the two following config files.
211
+ Embedded Ruby is allowed in the YAML configuration files. ERB will be evaluated at load time by default, and when the `evaluate_erb_in_yaml` configuration is set to `true`.
212
+
213
+ Consider the two following config files.
209
214
 
210
215
  * ```#{Rails.root}/config/settings.yml```
211
216
 
@@ -265,7 +270,10 @@ After installing `Config` in Rails, you will find automatically generated file t
265
270
 
266
271
  ### General
267
272
 
268
- * `const_name` - name of the object holing you settings. Default: `'Settings'`
273
+ * `const_name` - name of the object holding your settings. Default: `'Settings'`
274
+ * `evaluate_erb_in_yaml` - evaluate ERB in YAML config files. Set to false if the config file contains ERB that should not be evaluated at load time. Default: `true`
275
+ * `file_name` - name of the file to store general keys accessible in all environments. Default: `'settings'` - located at `config/settings.yml`
276
+ * `dir_name` - name of the directory to store environment-specific files. Default: `'settings'` - located at `config/settings/`
269
277
 
270
278
  ### Merge customization
271
279
 
@@ -420,7 +428,7 @@ ENV['Settings.section.server'] = 'google.com'
420
428
 
421
429
  It won't work with arrays, though.
422
430
 
423
- It is considered an error to use environment variables to simutaneously assign a "flat" value and a multi-level value to a key.
431
+ It is considered an error to use environment variables to simultaneously assign a "flat" value and a multi-level value to a key.
424
432
 
425
433
  ```ruby
426
434
  # Raises an error when settings are loaded
@@ -480,12 +488,83 @@ Settings.section.server # => 'google.com'
480
488
  Settings.section.ssl_enabled # => false
481
489
  ```
482
490
 
491
+ ### Working with AWS Secrets Manager
492
+
493
+ It is possible to parse variables stored in an AWS Secrets Manager Secret as if they were environment variables by using `Config::Sources::EnvSource`.
494
+
495
+ For example, the plaintext secret might look like this:
496
+
497
+ ```json
498
+ {
499
+ "Settings.foo": "hello",
500
+ "Settings.bar": "world",
501
+ }
502
+ ```
503
+
504
+ In order to load those settings, fetch the settings from AWS Secrets Manager, parse the plaintext as JSON, pass the resulting `Hash` into a new `EnvSource`, load the new source, and reload.
505
+
506
+ ```ruby
507
+ # fetch secrets from AWS
508
+ client = Aws::SecretsManager::Client.new
509
+ response = client.get_secret_value(secret_id: "#{ENV['ENVIRONMENT']}/my_application")
510
+ secrets = JSON.parse(response.secret_string)
511
+
512
+ # load secrets into config
513
+ secret_source = Config::Sources::EnvSource.new(secrets)
514
+ Settings.add_source!(secret_source)
515
+ Settings.reload!
516
+ ```
517
+
518
+ In this case, the following settings will be available:
519
+
520
+ ```ruby
521
+ Settings.foo # => "hello"
522
+ Settings.bar # => "world"
523
+ ```
524
+
525
+ By default, `EnvSource` will use configuration for `env_prefix`, `env_separator`, `env_converter`, and `env_parse_values`, but any of these can be overridden in the constructor.
526
+
527
+ ```ruby
528
+ secret_source = Config::Sources::EnvSource.new(secrets,
529
+ prefix: 'MyConfig',
530
+ separator: '__',
531
+ converter: nil,
532
+ parse_values: false)
533
+ ```
534
+
483
535
  ## Contributing
484
536
 
485
537
  You are very warmly welcome to help. Please follow our [contribution guidelines](CONTRIBUTING.md)
486
538
 
487
539
  Any and all contributions offered in any form, past present or future are understood to be in complete agreement and acceptance with [MIT](LICENSE) license.
488
540
 
541
+ ### Running specs
542
+
543
+ Setup
544
+
545
+ ```sh
546
+ bundle install
547
+ bundle exec appraisal install
548
+ ```
549
+
550
+ List defined appraisals:
551
+
552
+ ```sh
553
+ bundle exec appraisal list
554
+ ```
555
+
556
+ Run specs for specific appraisal:
557
+
558
+ ```sh
559
+ bundle exec appraisal rails-6.1 rspec
560
+ ```
561
+
562
+ Run specs for all appraisals:
563
+
564
+ ```sh
565
+ bundle exec appraisal rspec
566
+ ```
567
+
489
568
  ## Authors
490
569
 
491
570
  * [Piotr Kuczynski](http://github.com/pkuczynski)
data/config.gemspec CHANGED
@@ -1,6 +1,5 @@
1
- $:.push File.expand_path('../lib', __FILE__)
2
-
3
- require 'config/version'
1
+ require_relative 'lib/config/version'
2
+ require_relative 'lib/config/dry_validation_requirements'
4
3
 
5
4
  Gem::Specification.new do |s|
6
5
  s.name = 'config'
@@ -8,31 +7,34 @@ Gem::Specification.new do |s|
8
7
  s.date = Time.now.strftime '%F'
9
8
  s.authors = ['Piotr Kuczynski', 'Fred Wu', 'Jacques Crocker']
10
9
  s.email = %w[piotr.kuczynski@gmail.com ifredwu@gmail.com railsjedi@gmail.com]
11
- s.summary = 'Effortless multi-environment settings in Rails, Sinatra, Pandrino and others'
10
+ s.summary = 'Effortless multi-environment settings in Rails, Sinatra, Padrino and others'
12
11
  s.description = 'Easiest way to manage multi-environment settings in any ruby project or framework: ' +
13
- 'Rails, Sinatra, Pandrino and others'
12
+ 'Rails, Sinatra, Padrino and others'
14
13
  s.homepage = 'https://github.com/rubyconfig/config'
15
14
  s.license = 'MIT'
16
15
  s.extra_rdoc_files = %w[README.md CHANGELOG.md CONTRIBUTING.md LICENSE.md]
17
16
  s.rdoc_options = ['--charset=UTF-8']
18
- s.post_install_message = "\n\e[33mThanks for installing Config\e[0m
19
- Please consider donating to our open collective to help us maintain this project.
20
- \n
21
- Donate: \e[34mhttps://opencollective.com/rubyconfig/donate\e[0m\n"
22
17
 
18
+ s.metadata = {
19
+ 'changelog_uri' => "https://github.com/rubyconfig/config/blob/master/CHANGELOG.md",
20
+ 'funding_uri' => 'https://opencollective.com/rubyconfig/donate',
21
+ 'source_code_uri' => 'https://github.com/rubyconfig/config',
22
+ 'bug_tracker_uri' => 'https://github.com/rubyconfig/config/issues'
23
+ }
23
24
  s.files = `git ls-files`.split($/)
24
25
  s.files.select! { |file| /(^lib\/|^\w+.md$|\.gemspec$)/ =~ file }
25
26
 
26
27
  s.require_paths = ['lib']
27
- s.required_ruby_version = '>= 2.4.0'
28
+ s.required_ruby_version = '>= 2.6.0'
28
29
 
29
30
  s.add_dependency 'deep_merge', '~> 1.2', '>= 1.2.1'
30
- s.add_dependency 'dry-validation', '~> 1.0', '>= 1.0.0'
31
+ s.add_dependency 'ostruct'
31
32
 
33
+ s.add_development_dependency 'dry-validation', *Config::DryValidationRequirements::VERSIONS
32
34
  s.add_development_dependency 'rake', '~> 12.0', '>= 12.0.0'
33
35
 
34
36
  # Testing
35
- s.add_development_dependency 'appraisal', '~> 2.3', '>= 2.3.0'
37
+ s.add_development_dependency 'appraisal', '~> 2.5', '>= 2.5.0'
36
38
  s.add_development_dependency 'rspec', '~> 3.9', '>= 3.9.0'
37
39
 
38
40
  # Default RSpec run will test against latest Rails app
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Config
4
+ module DryValidationRequirements
5
+ VERSIONS = ['~> 1.0', '>= 1.0.0'].freeze
6
+
7
+ def self.load_dry_validation!
8
+ return if defined?(@load_dry_validation)
9
+
10
+ begin
11
+ require 'dry/validation/version'
12
+ version = Gem::Version.new(Dry::Validation::VERSION)
13
+ unless VERSIONS.all? { |req| Gem::Requirement.new(req).satisfied_by?(version) }
14
+ raise LoadError
15
+ end
16
+ rescue LoadError
17
+ raise ::Config::Error, 'Could not find a dry-validation version' \
18
+ ' matching requirements' \
19
+ " (#{VERSIONS.map(&:inspect) * ','})"
20
+ end
21
+
22
+ require 'dry/validation'
23
+ @load_dry_validation = true
24
+ nil
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,4 @@
1
+ module Config
2
+ class Error < StandardError
3
+ end
4
+ end
@@ -14,8 +14,8 @@ module Config
14
14
  def vars
15
15
  # Load only local options to Heroku
16
16
  Config.load_and_set_settings(
17
- Rails.root.join("config", "settings.local.yml").to_s,
18
- Rails.root.join("config", "settings", "#{environment}.local.yml").to_s,
17
+ Rails.root.join("config", "#{Config.file_name}.local.yml").to_s,
18
+ Rails.root.join("config", Config.dir_name, "#{environment}.local.yml").to_s,
19
19
  Rails.root.join("config", "environments", "#{environment}.local.yml").to_s
20
20
  )
21
21
 
@@ -9,7 +9,7 @@ module Config
9
9
 
10
10
  # Parse the settings before any of the initializers
11
11
  Config.load_and_set_settings(
12
- Config.setting_files(::Rails.root.join('config'), ::Rails.env)
12
+ Config.setting_files(::Rails.root.join('config'), Config.environment.nil? ? ::Rails.env : Config.environment.to_sym)
13
13
  )
14
14
  end
15
15
 
@@ -16,7 +16,7 @@ module Config
16
16
 
17
17
  def add_source!(source)
18
18
  # handle yaml file paths
19
- source = (Sources::YAMLSource.new(source)) if source.is_a?(String)
19
+ source = (Sources::YAMLSource.new(source)) if source.is_a?(String) || source.is_a?(Pathname)
20
20
  source = (Sources::HashSource.new(source)) if source.is_a?(Hash)
21
21
 
22
22
  @config_sources ||= []
@@ -24,54 +24,13 @@ module Config
24
24
  end
25
25
 
26
26
  def prepend_source!(source)
27
- source = (Sources::YAMLSource.new(source)) if source.is_a?(String)
27
+ source = (Sources::YAMLSource.new(source)) if source.is_a?(String) || source.is_a?(Pathname)
28
28
  source = (Sources::HashSource.new(source)) if source.is_a?(Hash)
29
29
 
30
30
  @config_sources ||= []
31
31
  @config_sources.unshift(source)
32
32
  end
33
33
 
34
- def reload_env!
35
- return self if ENV.nil? || ENV.empty?
36
-
37
- hash = Hash.new
38
-
39
- ENV.each do |variable, value|
40
- separator = Config.env_separator
41
- prefix = (Config.env_prefix || Config.const_name).to_s.split(separator)
42
-
43
- keys = variable.to_s.split(separator)
44
-
45
- next if keys.shift(prefix.size) != prefix
46
-
47
- keys.map! { |key|
48
- case Config.env_converter
49
- when :downcase then
50
- key.downcase.to_sym
51
- when nil then
52
- key.to_sym
53
- else
54
- raise "Invalid ENV variables name converter: #{Config.env_converter}"
55
- end
56
- }
57
-
58
- leaf = keys[0...-1].inject(hash) { |h, key|
59
- h[key] ||= {}
60
- }
61
-
62
- unless leaf.is_a?(Hash)
63
- conflicting_key = (prefix + keys[0...-1]).join(separator)
64
- raise "Environment variable #{variable} conflicts with variable #{conflicting_key}"
65
- end
66
-
67
- leaf[keys.last] = Config.env_parse_values ? __value(value) : value
68
- end
69
-
70
- merge!(hash)
71
- end
72
-
73
- alias :load_env! :reload_env!
74
-
75
34
  # look through all our sources and rebuild the configuration
76
35
  def reload!
77
36
  conf = {}
@@ -96,7 +55,6 @@ module Config
96
55
  # swap out the contents of the OStruct with a hash (need to recursively convert)
97
56
  marshal_load(__convert(conf).marshal_dump)
98
57
 
99
- reload_env! if Config.use_env
100
58
  validate!
101
59
 
102
60
  self
@@ -123,6 +81,8 @@ module Config
123
81
  result
124
82
  end
125
83
 
84
+ alias :to_h :to_hash
85
+
126
86
  def each(*args, &block)
127
87
  marshal_dump.each(*args, &block)
128
88
  end
@@ -152,13 +112,17 @@ module Config
152
112
  end
153
113
 
154
114
  # Some keywords that don't play nicely with OpenStruct
155
- SETTINGS_RESERVED_NAMES = %w[select collect test count zip min max exit!].freeze
115
+ SETTINGS_RESERVED_NAMES = %w[select collect test count zip min max exit! table].freeze
116
+
117
+ # Some keywords that don't play nicely with Rails 7.*
118
+ RAILS_RESERVED_NAMES = %w[maximum minimum].freeze
156
119
 
157
120
  # An alternative mechanism for property access.
158
121
  # This let's you do foo['bar'] along with foo.bar.
159
122
  def [](param)
160
123
  return super if SETTINGS_RESERVED_NAMES.include?(param)
161
- send("#{param}")
124
+ return super if RAILS_RESERVED_NAMES.include?(param)
125
+ public_send("#{param}")
162
126
  end
163
127
 
164
128
  def []=(param, value)
@@ -171,12 +135,18 @@ module Config
171
135
  end
172
136
  end
173
137
 
138
+ RAILS_RESERVED_NAMES.each do |name|
139
+ define_method name do
140
+ self[name]
141
+ end
142
+ end
143
+
174
144
  def key?(key)
175
- table.key?(key)
145
+ @table.key?(key)
176
146
  end
177
147
 
178
148
  def has_key?(key)
179
- table.has_key?(key)
149
+ @table.has_key?(key)
180
150
  end
181
151
 
182
152
  def method_missing(method_name, *args)
@@ -221,17 +191,5 @@ module Config
221
191
  end
222
192
  s
223
193
  end
224
-
225
- # Try to convert string to a correct type
226
- def __value(v)
227
- case v
228
- when 'false'
229
- false
230
- when 'true'
231
- true
232
- else
233
- Integer(v) rescue Float(v) rescue v
234
- end
235
- end
236
194
  end
237
195
  end
@@ -0,0 +1,94 @@
1
+ module Config
2
+ module Sources
3
+ # Allows settings to be loaded from a "flat" hash with string keys, like ENV.
4
+ class EnvSource
5
+ attr_reader :prefix
6
+ attr_reader :separator
7
+ attr_reader :converter
8
+ attr_reader :parse_values
9
+ attr_reader :parse_arrays
10
+
11
+ def initialize(env,
12
+ prefix: Config.env_prefix || Config.const_name,
13
+ separator: Config.env_separator,
14
+ converter: Config.env_converter,
15
+ parse_values: Config.env_parse_values,
16
+ parse_arrays: Config.env_parse_arrays)
17
+ @env = env
18
+ @prefix = prefix.to_s.split(separator)
19
+ @separator = separator
20
+ @converter = converter
21
+ @parse_values = parse_values
22
+ @parse_arrays = parse_arrays
23
+ end
24
+
25
+ def load
26
+ return {} if @env.nil? || @env.empty?
27
+
28
+ hash = Hash.new
29
+
30
+ @env.each do |variable, value|
31
+ keys = variable.to_s.split(separator)
32
+
33
+ next if keys.shift(prefix.size) != prefix
34
+
35
+ keys.map! { |key|
36
+ case converter
37
+ when :downcase then
38
+ key.downcase
39
+ when nil then
40
+ key
41
+ else
42
+ raise "Invalid ENV variables name converter: #{converter}"
43
+ end
44
+ }
45
+
46
+ leaf = keys[0...-1].inject(hash) { |h, key|
47
+ h[key] ||= {}
48
+ }
49
+
50
+ unless leaf.is_a?(Hash)
51
+ conflicting_key = (prefix + keys[0...-1]).join(separator)
52
+ raise "Environment variable #{variable} conflicts with variable #{conflicting_key}"
53
+ end
54
+
55
+ leaf[keys.last] = parse_values ? __value(value) : value
56
+ end
57
+
58
+ parse_arrays ? convert_hashes_to_arrays(hash) : hash
59
+ end
60
+
61
+ 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
80
+
81
+ # Try to convert string to a correct type
82
+ def __value(v)
83
+ case v
84
+ when 'false'
85
+ false
86
+ when 'true'
87
+ true
88
+ else
89
+ Integer(v) rescue Float(v) rescue v
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
@@ -5,21 +5,27 @@ module Config
5
5
  module Sources
6
6
  class YAMLSource
7
7
  attr_accessor :path
8
+ attr_reader :evaluate_erb
8
9
 
9
- def initialize(path)
10
+ def initialize(path, evaluate_erb: Config.evaluate_erb_in_yaml)
10
11
  @path = path.to_s
12
+ @evaluate_erb = !!evaluate_erb
11
13
  end
12
14
 
13
15
  # returns a config hash from the YML file
14
16
  def load
15
- result = YAML.load(ERB.new(IO.read(@path)).result) if @path and File.exist?(@path)
17
+ if @path and File.exist?(@path)
18
+ file_contents = IO.read(@path)
19
+ file_contents = ERB.new(file_contents).result if evaluate_erb
20
+ result = YAML.respond_to?(:unsafe_load) ? YAML.unsafe_load(file_contents) : YAML.load(file_contents)
21
+ end
16
22
 
17
23
  result || {}
18
24
 
19
- rescue Psych::SyntaxError => e
20
- raise "YAML syntax error occurred while parsing #{@path}. " \
21
- "Please note that YAML must be consistently indented using spaces. Tabs are not allowed. " \
22
- "Error: #{e.message}"
25
+ rescue Psych::SyntaxError => e
26
+ raise "YAML syntax error occurred while parsing #{@path}. " \
27
+ "Please note that YAML must be consistently indented using spaces. Tabs are not allowed. " \
28
+ "Error: #{e.message}"
23
29
  end
24
30
  end
25
31
  end
@@ -1,6 +1,8 @@
1
+ require_relative "../error"
2
+
1
3
  module Config
2
4
  module Validation
3
- class Error < StandardError
5
+ class Error < ::Config::Error
4
6
 
5
7
  def self.format(v_res)
6
8
  v_res.errors.group_by(&:path).map do |path, messages|
@@ -1,3 +1,6 @@
1
+ require_relative '../dry_validation_requirements'
2
+ require_relative '../error'
3
+
1
4
  module Config
2
5
  module Validation
3
6
  module Schema
@@ -9,7 +12,7 @@ module Config
9
12
  def schema(&block)
10
13
  if block_given?
11
14
  # Delay require until optional schema validation is requested
12
- require 'dry-validation'
15
+ Config::DryValidationRequirements.load_dry_validation!
13
16
  @schema = Dry::Schema.define(&block)
14
17
  else
15
18
  @schema
@@ -4,6 +4,10 @@ module Config
4
4
  module Validation
5
5
  module Validate
6
6
  def validate!
7
+ return unless Config.validation_contract || Config.schema
8
+
9
+ Config::DryValidationRequirements.load_dry_validation!
10
+
7
11
  validate_using!(Config.validation_contract)
8
12
  validate_using!(Config.schema)
9
13
  end
@@ -1,3 +1,3 @@
1
1
  module Config
2
- VERSION = '2.2.3'.freeze
2
+ VERSION = '5.5.2'.freeze
3
3
  end
data/lib/config.rb CHANGED
@@ -1,11 +1,12 @@
1
- require 'config/compatibility'
2
1
  require 'config/options'
3
2
  require 'config/configuration'
3
+ require 'config/dry_validation_requirements'
4
4
  require 'config/version'
5
5
  require 'config/sources/yaml_source'
6
6
  require 'config/sources/hash_source'
7
+ require 'config/sources/env_source'
7
8
  require 'config/validation/schema'
8
- require 'deep_merge'
9
+ require 'deep_merge/core'
9
10
 
10
11
  module Config
11
12
  extend Config::Validation::Schema
@@ -17,13 +18,18 @@ module Config
17
18
  env_separator: '.',
18
19
  env_converter: :downcase,
19
20
  env_parse_values: true,
21
+ env_parse_arrays: false,
20
22
  fail_on_missing: false,
23
+ file_name: 'settings',
24
+ dir_name: 'settings',
21
25
  # deep_merge options
22
26
  knockout_prefix: nil,
23
27
  merge_nil_values: true,
24
28
  overwrite_arrays: true,
25
29
  merge_hash_arrays: false,
26
- validation_contract: nil
30
+ validation_contract: nil,
31
+ evaluate_erb_in_yaml: true,
32
+ environment: nil
27
33
  )
28
34
 
29
35
  def self.setup
@@ -33,29 +39,31 @@ module Config
33
39
 
34
40
  # Create a populated Options instance from a settings file. If a second file is given, then the sections of that
35
41
  # file will overwrite existing sections of the first file.
36
- def self.load_files(*files)
42
+ def self.load_files(*sources)
37
43
  config = Options.new
38
44
 
39
45
  # add settings sources
40
- [files].flatten.compact.uniq.each do |file|
41
- config.add_source!(file.to_s)
46
+ [sources].flatten.compact.each do |source|
47
+ config.add_source!(source)
42
48
  end
43
49
 
50
+ config.add_source!(Sources::EnvSource.new(ENV)) if Config.use_env
51
+
44
52
  config.load!
45
53
  config
46
54
  end
47
55
 
48
56
  # Loads and sets the settings constant!
49
- def self.load_and_set_settings(*files)
57
+ def self.load_and_set_settings(*sources)
50
58
  name = Config.const_name
51
59
  Object.send(:remove_const, name) if Object.const_defined?(name)
52
- Object.const_set(name, Config.load_files(files))
60
+ Object.const_set(name, Config.load_files(sources))
53
61
  end
54
62
 
55
63
  def self.setting_files(config_root, env)
56
64
  [
57
- File.join(config_root, 'settings.yml').to_s,
58
- File.join(config_root, 'settings', "#{env}.yml").to_s,
65
+ File.join(config_root, "#{Config.file_name}.yml").to_s,
66
+ File.join(config_root, Config.dir_name, "#{env}.yml").to_s,
59
67
  File.join(config_root, 'environments', "#{env}.yml").to_s,
60
68
  *local_setting_files(config_root, env)
61
69
  ].freeze
@@ -63,8 +71,8 @@ module Config
63
71
 
64
72
  def self.local_setting_files(config_root, env)
65
73
  [
66
- (File.join(config_root, 'settings.local.yml').to_s if env != 'test'),
67
- File.join(config_root, 'settings', "#{env}.local.yml").to_s,
74
+ (File.join(config_root, "#{Config.file_name}.local.yml").to_s if env != 'test'),
75
+ File.join(config_root, Config.dir_name, "#{env}.local.yml").to_s,
68
76
  File.join(config_root, 'environments', "#{env}.local.yml").to_s
69
77
  ].compact
70
78
  end
@@ -75,7 +83,7 @@ module Config
75
83
  end
76
84
 
77
85
  # Rails integration
78
- require('config/integrations/rails/railtie') if defined?(::Rails)
86
+ require('config/integrations/rails/railtie') if defined?(::Rails::Railtie)
79
87
 
80
88
  # Sinatra integration
81
89
  require('config/integrations/sinatra') if defined?(::Sinatra)
@@ -12,18 +12,18 @@ module Config
12
12
  end
13
13
 
14
14
  def copy_settings
15
- template "settings.yml", "config/settings.yml"
16
- template "settings.local.yml", "config/settings.local.yml"
17
- directory "settings", "config/settings"
15
+ template "settings.yml", "config/#{Config.file_name}.yml"
16
+ template "settings.local.yml", "config/#{Config.file_name}.local.yml"
17
+ directory "settings", "config/#{Config.dir_name}"
18
18
  end
19
19
 
20
20
  def modify_gitignore
21
- create_file '.gitignore' unless File.exists? '.gitignore'
21
+ create_file '.gitignore' unless File.exist? '.gitignore'
22
22
 
23
23
  append_to_file '.gitignore' do
24
- "\n" +
25
- "config/settings.local.yml\n" +
26
- "config/settings/*.local.yml\n" +
24
+ "\n" +
25
+ "config/#{Config.file_name}.local.yml\n" +
26
+ "config/#{Config.dir_name}/*.local.yml\n" +
27
27
  "config/environments/*.local.yml\n"
28
28
  end
29
29
  end
@@ -15,6 +15,11 @@ Config.setup do |config|
15
15
  #
16
16
  # config.overwrite_arrays = true
17
17
 
18
+ # Defines current environment, affecting which settings file will be loaded.
19
+ # Default: `Rails.env`
20
+ #
21
+ # config.environment = ENV.fetch('ENVIRONMENT', :development)
22
+
18
23
  # Load environment variables from the `ENV` object and override any settings defined in files.
19
24
  #
20
25
  # config.use_env = false
@@ -52,4 +57,12 @@ Config.setup do |config|
52
57
  # required(:email).filled(format?: EMAIL_REGEX)
53
58
  # end
54
59
 
60
+ # Evaluate ERB in YAML config files at load time.
61
+ #
62
+ # config.evaluate_erb_in_yaml = true
63
+
64
+ # Name of directory and file to store config keys
65
+ #
66
+ # config.file_name = 'settings'
67
+ # config.dir_name = 'settings'
55
68
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: config
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.3
4
+ version: 5.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Kuczynski
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2020-12-09 00:00:00.000000000 Z
13
+ date: 2024-09-23 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: deep_merge
@@ -32,6 +32,20 @@ dependencies:
32
32
  - - ">="
33
33
  - !ruby/object:Gem::Version
34
34
  version: 1.2.1
35
+ - !ruby/object:Gem::Dependency
36
+ name: ostruct
37
+ requirement: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ type: :runtime
43
+ prerelease: false
44
+ version_requirements: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
35
49
  - !ruby/object:Gem::Dependency
36
50
  name: dry-validation
37
51
  requirement: !ruby/object:Gem::Requirement
@@ -42,7 +56,7 @@ dependencies:
42
56
  - - ">="
43
57
  - !ruby/object:Gem::Version
44
58
  version: 1.0.0
45
- type: :runtime
59
+ type: :development
46
60
  prerelease: false
47
61
  version_requirements: !ruby/object:Gem::Requirement
48
62
  requirements:
@@ -78,20 +92,20 @@ dependencies:
78
92
  requirements:
79
93
  - - "~>"
80
94
  - !ruby/object:Gem::Version
81
- version: '2.3'
95
+ version: '2.5'
82
96
  - - ">="
83
97
  - !ruby/object:Gem::Version
84
- version: 2.3.0
98
+ version: 2.5.0
85
99
  type: :development
86
100
  prerelease: false
87
101
  version_requirements: !ruby/object:Gem::Requirement
88
102
  requirements:
89
103
  - - "~>"
90
104
  - !ruby/object:Gem::Version
91
- version: '2.3'
105
+ version: '2.5'
92
106
  - - ">="
93
107
  - !ruby/object:Gem::Version
94
- version: 2.3.0
108
+ version: 2.5.0
95
109
  - !ruby/object:Gem::Dependency
96
110
  name: rspec
97
111
  requirement: !ruby/object:Gem::Requirement
@@ -116,44 +130,72 @@ dependencies:
116
130
  name: bootsnap
117
131
  requirement: !ruby/object:Gem::Requirement
118
132
  requirements:
119
- - - "~>"
133
+ - - ">="
120
134
  - !ruby/object:Gem::Version
121
- version: '1.4'
135
+ version: 1.16.0
122
136
  type: :development
123
137
  prerelease: false
124
138
  version_requirements: !ruby/object:Gem::Requirement
125
139
  requirements:
126
- - - "~>"
140
+ - - ">="
127
141
  - !ruby/object:Gem::Version
128
- version: '1.4'
142
+ version: 1.16.0
129
143
  - !ruby/object:Gem::Dependency
130
144
  name: rails
131
145
  requirement: !ruby/object:Gem::Requirement
132
146
  requirements:
133
147
  - - '='
134
148
  - !ruby/object:Gem::Version
135
- version: 6.0.3.1
149
+ version: 7.1.0
136
150
  type: :development
137
151
  prerelease: false
138
152
  version_requirements: !ruby/object:Gem::Requirement
139
153
  requirements:
140
154
  - - '='
141
155
  - !ruby/object:Gem::Version
142
- version: 6.0.3.1
156
+ version: 7.1.0
143
157
  - !ruby/object:Gem::Dependency
144
158
  name: rspec-rails
145
159
  requirement: !ruby/object:Gem::Requirement
146
160
  requirements:
147
161
  - - "~>"
148
162
  - !ruby/object:Gem::Version
149
- version: '3.7'
163
+ version: 6.0.3
150
164
  type: :development
151
165
  prerelease: false
152
166
  version_requirements: !ruby/object:Gem::Requirement
153
167
  requirements:
154
168
  - - "~>"
155
169
  - !ruby/object:Gem::Version
156
- version: '3.7'
170
+ version: 6.0.3
171
+ - !ruby/object:Gem::Dependency
172
+ name: sprockets-rails
173
+ requirement: !ruby/object:Gem::Requirement
174
+ requirements:
175
+ - - "~>"
176
+ - !ruby/object:Gem::Version
177
+ version: 3.4.2
178
+ type: :development
179
+ prerelease: false
180
+ version_requirements: !ruby/object:Gem::Requirement
181
+ requirements:
182
+ - - "~>"
183
+ - !ruby/object:Gem::Version
184
+ version: 3.4.2
185
+ - !ruby/object:Gem::Dependency
186
+ name: psych
187
+ requirement: !ruby/object:Gem::Requirement
188
+ requirements:
189
+ - - ">="
190
+ - !ruby/object:Gem::Version
191
+ version: '4'
192
+ type: :development
193
+ prerelease: false
194
+ version_requirements: !ruby/object:Gem::Requirement
195
+ requirements:
196
+ - - ">="
197
+ - !ruby/object:Gem::Version
198
+ version: '4'
157
199
  - !ruby/object:Gem::Dependency
158
200
  name: mdl
159
201
  requirement: !ruby/object:Gem::Requirement
@@ -189,7 +231,7 @@ dependencies:
189
231
  - !ruby/object:Gem::Version
190
232
  version: 0.85.0
191
233
  description: 'Easiest way to manage multi-environment settings in any ruby project
192
- or framework: Rails, Sinatra, Pandrino and others'
234
+ or framework: Rails, Sinatra, Padrino and others'
193
235
  email:
194
236
  - piotr.kuczynski@gmail.com
195
237
  - ifredwu@gmail.com
@@ -208,13 +250,15 @@ files:
208
250
  - README.md
209
251
  - config.gemspec
210
252
  - lib/config.rb
211
- - lib/config/compatibility.rb
212
253
  - lib/config/configuration.rb
254
+ - lib/config/dry_validation_requirements.rb
255
+ - lib/config/error.rb
213
256
  - lib/config/integrations/heroku.rb
214
257
  - lib/config/integrations/rails/railtie.rb
215
258
  - lib/config/integrations/sinatra.rb
216
259
  - lib/config/options.rb
217
260
  - lib/config/rack/reloader.rb
261
+ - lib/config/sources/env_source.rb
218
262
  - lib/config/sources/hash_source.rb
219
263
  - lib/config/sources/yaml_source.rb
220
264
  - lib/config/tasks/heroku.rake
@@ -232,9 +276,12 @@ files:
232
276
  homepage: https://github.com/rubyconfig/config
233
277
  licenses:
234
278
  - MIT
235
- metadata: {}
236
- post_install_message: "\n\e[33mThanks for installing Config\e[0m\nPlease consider
237
- donating to our open collective to help us maintain this project.\n\n\nDonate: \e[34mhttps://opencollective.com/rubyconfig/donate\e[0m\n"
279
+ metadata:
280
+ changelog_uri: https://github.com/rubyconfig/config/blob/master/CHANGELOG.md
281
+ funding_uri: https://opencollective.com/rubyconfig/donate
282
+ source_code_uri: https://github.com/rubyconfig/config
283
+ bug_tracker_uri: https://github.com/rubyconfig/config/issues
284
+ post_install_message:
238
285
  rdoc_options:
239
286
  - "--charset=UTF-8"
240
287
  require_paths:
@@ -243,15 +290,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
243
290
  requirements:
244
291
  - - ">="
245
292
  - !ruby/object:Gem::Version
246
- version: 2.4.0
293
+ version: 2.6.0
247
294
  required_rubygems_version: !ruby/object:Gem::Requirement
248
295
  requirements:
249
296
  - - ">="
250
297
  - !ruby/object:Gem::Version
251
298
  version: '0'
252
299
  requirements: []
253
- rubygems_version: 3.1.2
300
+ rubygems_version: 3.5.18
254
301
  signing_key:
255
302
  specification_version: 4
256
- summary: Effortless multi-environment settings in Rails, Sinatra, Pandrino and others
303
+ summary: Effortless multi-environment settings in Rails, Sinatra, Padrino and others
257
304
  test_files: []
@@ -1,3 +0,0 @@
1
- if defined?(RbConfig) && defined?(Config)
2
- Object.send :remove_const, :Config
3
- end