Skip to content

Commit 3dd6817

Browse files
authored
Support arbitrary sources in Config.load_files and Config.load_and_set_settings (#315)
* Add instructions for running specs * Backfile test for Pathname support in load_files There's a .to_s call in there that's likely to support these kinds of objects, but there wasn't a test for it. * Rename `file` variables to `source` In an upcoming change, we'll allow arbirtary sources as parameters to these methods, instead of just filenames. The method names remain unchanged for now for backwards compatibility. * Support arbitrary Source objects in Config.load_files * Add test for loading HashSource from load_files * Remove uniq call in load_files This uniq call causes issues when mixing the types of sources. This change can technically break some applications that were depending on the de-deduplication of source files. * Remove .to_s call in load_files on source This change effectively conslidates the logic for coercing source specifications to Source objects into `Config::Options#add_source!`. For sources specified as Strings or Pathnames, there is effectively no change, but for sources specified as something else that responds to `.to_s`, this change could be breaking. In those cases, application developers can explicitly call `.to_s` on those objects before handing them to config. * Add CHANGELOG entry
1 parent 9c35a5d commit 3dd6817

5 files changed

Lines changed: 68 additions & 8 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22

33
## Unreleased
44

5-
...
5+
### BREAKING CHANGES
6+
7+
* 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:
8+
* Previously, `Config.load_files` (called from `Config.load_and_set_settings`) would call `.to_s` on each of its arguments. Now, this responsibility is defered 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`.
9+
* 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`.
610

711
## 3.1.1
812

README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,33 @@ You are very warmly welcome to help. Please follow our [contribution guidelines]
533533

534534
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.
535535

536+
### Running specs
537+
538+
Setup
539+
540+
```sh
541+
bundle install
542+
bundle exec appraisal install
543+
```
544+
545+
List defined appraisals:
546+
547+
```sh
548+
bundle exec appraisal list
549+
```
550+
551+
Run specs for specific appraisal:
552+
553+
```sh
554+
bundle exec appraisal rails-6.1 rspec
555+
```
556+
557+
Run specs for all appraisals:
558+
559+
```sh
560+
bundle exec appraisal rspec
561+
```
562+
536563
## Authors
537564

538565
* [Piotr Kuczynski](http://github.com/pkuczynski)

lib/config.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ def self.setup
3535

3636
# Create a populated Options instance from a settings file. If a second file is given, then the sections of that
3737
# file will overwrite existing sections of the first file.
38-
def self.load_files(*files)
38+
def self.load_files(*sources)
3939
config = Options.new
4040

4141
# add settings sources
42-
[files].flatten.compact.uniq.each do |file|
43-
config.add_source!(file.to_s)
42+
[sources].flatten.compact.each do |source|
43+
config.add_source!(source)
4444
end
4545

4646
config.add_source!(Sources::EnvSource.new(ENV)) if Config.use_env
@@ -50,10 +50,10 @@ def self.load_files(*files)
5050
end
5151

5252
# Loads and sets the settings constant!
53-
def self.load_and_set_settings(*files)
53+
def self.load_and_set_settings(*sources)
5454
name = Config.const_name
5555
Object.send(:remove_const, name) if Object.const_defined?(name)
56-
Object.const_set(name, Config.load_files(files))
56+
Object.const_set(name, Config.load_files(sources))
5757
end
5858

5959
def self.setting_files(config_root, env)

lib/config/options.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@ def empty?
1616

1717
def add_source!(source)
1818
# 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)
2020
source = (Sources::HashSource.new(source)) if source.is_a?(Hash)
2121

2222
@config_sources ||= []
2323
@config_sources << source
2424
end
2525

2626
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)
2828
source = (Sources::HashSource.new(source)) if source.is_a?(Hash)
2929

3030
@config_sources ||= []

spec/config_spec.rb

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,35 @@
4545
expect(config.another).to eq("something")
4646
end
4747

48+
it 'should load config files specified as Pathname objects' do
49+
path = Pathname.new(fixture_path).join('settings.yml')
50+
config = Config.load_files(path)
51+
expect(config.server).to eq('google.com')
52+
end
53+
54+
it 'should load config files specified as objects responding to :load' do
55+
source = double 'source'
56+
allow(source).to receive(:load) do
57+
{ 'server' => 'google.com' }
58+
end
59+
config = Config.load_files(source)
60+
expect(config.server).to eq('google.com')
61+
end
62+
63+
it 'should load config from HashSource' do
64+
source = Config::Sources::HashSource.new({ 'server' => 'google.com' })
65+
config = Config.load_files(source)
66+
expect(config.server).to eq('google.com')
67+
end
68+
69+
it 'should load config from files and HashSource' do
70+
file_source = "#{fixture_path}/settings.yml"
71+
hash_source = Config::Sources::HashSource.new({ 'size' => 12 })
72+
config = Config.load_files(file_source, hash_source)
73+
expect(config.server).to eq('google.com')
74+
expect(config.size).to eq(12)
75+
end
76+
4877
it "should load empty config for a missing file path" do
4978
config = Config.load_files("#{fixture_path}/some_file_that_doesnt_exist.yml")
5079
expect(config).to be_empty

0 commit comments

Comments
 (0)