configurate 0.1.0 → 0.5.0
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 +5 -5
- data/Changelog.md +30 -0
- data/README.md +96 -20
- data/lib/configurate.rb +26 -15
- data/lib/configurate/lookup_chain.rb +19 -17
- data/lib/configurate/provider.rb +34 -27
- data/lib/configurate/provider/dynamic.rb +34 -17
- data/lib/configurate/provider/env.rb +18 -14
- data/lib/configurate/provider/string_hash.rb +46 -0
- data/lib/configurate/provider/toml.rb +39 -0
- data/lib/configurate/provider/yaml.rb +26 -32
- data/lib/configurate/proxy.rb +42 -13
- data/lib/configurate/setting_path.rb +20 -8
- data/spec/configurate/lookup_chain_spec.rb +11 -9
- data/spec/configurate/provider/dynamic_spec.rb +13 -5
- data/spec/configurate/provider/env_spec.rb +13 -11
- data/spec/configurate/provider/string_hash_spec.rb +82 -0
- data/spec/configurate/provider/toml_spec.rb +112 -0
- data/spec/configurate/provider/yaml_spec.rb +42 -18
- data/spec/configurate/provider_spec.rb +15 -2
- data/spec/configurate/proxy_spec.rb +33 -7
- data/spec/configurate/setting_path_spec.rb +39 -20
- data/spec/configurate_spec.rb +5 -3
- data/spec/spec_helper.rb +8 -5
- metadata +31 -13
- checksums.yaml.gz.asc +0 -11
- data.tar.gz.asc +0 -11
- metadata.gz.asc +0 -11
@@ -1,16 +1,18 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
2
4
|
|
3
5
|
describe Configurate::Provider::Dynamic do
|
4
6
|
subject { described_class.new }
|
5
7
|
describe "#lookup_path" do
|
6
8
|
it "returns nil if the setting was never set" do
|
7
|
-
expect(subject.lookup_path
|
9
|
+
expect(subject.lookup_path(Configurate::SettingPath.new(["not_me"]))).to be_nil
|
8
10
|
end
|
9
11
|
|
10
12
|
it "remembers the setting if it ends with =" do
|
11
13
|
subject.lookup_path Configurate::SettingPath.new(["find_me", "later="]), "there"
|
12
14
|
|
13
|
-
expect(subject.lookup_path
|
15
|
+
expect(subject.lookup_path(Configurate::SettingPath.new(%w[find_me later]))).to eq "there"
|
14
16
|
end
|
15
17
|
|
16
18
|
it "calls .get on the argument if a proxy object is given" do
|
@@ -20,8 +22,14 @@ describe Configurate::Provider::Dynamic do
|
|
20
22
|
end
|
21
23
|
|
22
24
|
it "resolves nested calls after group assignment" do
|
23
|
-
subject.lookup_path Configurate::SettingPath.new([
|
24
|
-
expect(subject.lookup_path
|
25
|
+
subject.lookup_path Configurate::SettingPath.new(%w[find_me later=]), "a" => "b"
|
26
|
+
expect(subject.lookup_path(Configurate::SettingPath.new(%w[find_me later a]))).to eq "b"
|
27
|
+
end
|
28
|
+
|
29
|
+
it "clears out all overrides on reset_dynamic!" do
|
30
|
+
subject.lookup_path Configurate::SettingPath.new(["find_me", "later="]), "there"
|
31
|
+
expect(subject.lookup_path(Configurate::SettingPath.new(["reset_dynamic!"]))).to eq true
|
32
|
+
expect(subject.lookup_path(Configurate::SettingPath.new(%w[find_me later]))).to_not eq "there"
|
25
33
|
end
|
26
34
|
end
|
27
35
|
end
|
@@ -1,32 +1,34 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
2
4
|
|
3
5
|
describe Configurate::Provider::Env do
|
4
6
|
subject { described_class.new }
|
5
|
-
let(:existing_path) { [
|
6
|
-
let(:not_existing_path) { [
|
7
|
-
let(:array_path) { [
|
7
|
+
let(:existing_path) { %w[existing setting] }
|
8
|
+
let(:not_existing_path) { %w[not existing path] }
|
9
|
+
let(:array_path) { ["array"] }
|
8
10
|
before(:all) do
|
9
|
-
ENV[
|
10
|
-
ENV[
|
11
|
+
ENV["EXISTING_SETTING"] = "there"
|
12
|
+
ENV["ARRAY"] = "foo,bar,baz"
|
11
13
|
end
|
12
14
|
|
13
15
|
after(:all) do
|
14
|
-
ENV[
|
15
|
-
ENV[
|
16
|
+
ENV["EXISTING_SETTING"] = nil
|
17
|
+
ENV["ARRAY"] = nil
|
16
18
|
end
|
17
19
|
|
18
|
-
describe
|
20
|
+
describe "#lookup_path" do
|
19
21
|
it "joins and upcases the path" do
|
20
22
|
expect(ENV).to receive(:[]).with("EXISTING_SETTING")
|
21
23
|
subject.lookup_path existing_path
|
22
24
|
end
|
23
25
|
|
24
26
|
it "returns nil if the setting isn't available" do
|
25
|
-
expect(subject.lookup_path
|
27
|
+
expect(subject.lookup_path(not_existing_path)).to be_nil
|
26
28
|
end
|
27
29
|
|
28
30
|
it "makes an array out of comma separated values" do
|
29
|
-
expect(subject.lookup_path
|
31
|
+
expect(subject.lookup_path(array_path)).to eq %w[foo bar baz]
|
30
32
|
end
|
31
33
|
|
32
34
|
it "returns a unfrozen string" do
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
describe Configurate::Provider::StringHash do
|
6
|
+
let(:settings) {
|
7
|
+
{
|
8
|
+
"toplevel" => "bar",
|
9
|
+
"some" => {
|
10
|
+
"nested" => {"some" => "lala", "setting" => "foo"}
|
11
|
+
}
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
describe "#initialize" do
|
16
|
+
it "raises if the argument is not hash" do
|
17
|
+
expect {
|
18
|
+
described_class.new "foo"
|
19
|
+
}.to raise_error ArgumentError
|
20
|
+
end
|
21
|
+
|
22
|
+
context "with a namespace" do
|
23
|
+
it "looks in the hash for that namespace" do
|
24
|
+
namespace = "some.nested"
|
25
|
+
provider = described_class.new settings, namespace: namespace
|
26
|
+
expect(provider.instance_variable_get(:@settings)).to eq settings["some"]["nested"]
|
27
|
+
end
|
28
|
+
|
29
|
+
it "raises if the namespace isn't found" do
|
30
|
+
expect {
|
31
|
+
described_class.new({}, namespace: "bar")
|
32
|
+
}.to raise_error ArgumentError
|
33
|
+
end
|
34
|
+
|
35
|
+
it "works with an empty namespace in the file" do
|
36
|
+
expect {
|
37
|
+
described_class.new({"foo" => {"bar" => nil}}, namespace: "foo.bar")
|
38
|
+
}.to_not raise_error
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "with required set to false" do
|
43
|
+
it "doesn't raise if a namespace isn't found" do
|
44
|
+
expect {
|
45
|
+
silence_stderr do
|
46
|
+
described_class.new({}, namespace: "foo", required: false)
|
47
|
+
end
|
48
|
+
}.not_to raise_error
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "#lookup_path" do
|
54
|
+
before do
|
55
|
+
@provider = described_class.new settings
|
56
|
+
end
|
57
|
+
|
58
|
+
it "looks up the whole nesting" do
|
59
|
+
expect(@provider.lookup_path(%w[some nested some])).to eq settings["some"]["nested"]["some"]
|
60
|
+
end
|
61
|
+
|
62
|
+
it "returns nil if no setting is found" do
|
63
|
+
expect(@provider.lookup_path(["not_me"])).to be_nil
|
64
|
+
end
|
65
|
+
|
66
|
+
context "with raise_on_missing set to true" do
|
67
|
+
before do
|
68
|
+
@provider = described_class.new settings, raise_on_missing: true
|
69
|
+
end
|
70
|
+
|
71
|
+
it "looks up the whole nesting" do
|
72
|
+
expect(@provider.lookup_path(%w[some nested some])).to eq settings["some"]["nested"]["some"]
|
73
|
+
end
|
74
|
+
|
75
|
+
it "returns nil if no setting is found" do
|
76
|
+
expect {
|
77
|
+
@provider.lookup_path ["not_me"]
|
78
|
+
}.to raise_error Configurate::MissingSetting
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
require "configurate/provider/toml"
|
5
|
+
|
6
|
+
describe Configurate::Provider::TOML do
|
7
|
+
PARSER = Configurate::Provider::TOML::PARSER
|
8
|
+
|
9
|
+
let(:settings) {
|
10
|
+
{
|
11
|
+
"toplevel" => "bar",
|
12
|
+
"some" => {
|
13
|
+
"nested" => {"some" => "lala", "setting" => "foo"}
|
14
|
+
}
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
describe "#initialize" do
|
19
|
+
it "loads the file" do
|
20
|
+
file = "foobar.toml"
|
21
|
+
expect(PARSER).to receive(:load_file).with(file).and_return({})
|
22
|
+
described_class.new file
|
23
|
+
end
|
24
|
+
|
25
|
+
it "raises if the file is not found" do
|
26
|
+
allow(PARSER).to receive(:load_file).and_raise(Errno::ENOENT)
|
27
|
+
expect {
|
28
|
+
silence_stderr do
|
29
|
+
described_class.new "foo"
|
30
|
+
end
|
31
|
+
}.to raise_error Errno::ENOENT
|
32
|
+
end
|
33
|
+
|
34
|
+
context "with a namespace" do
|
35
|
+
it "looks in the file for that namespace" do
|
36
|
+
namespace = "some.nested"
|
37
|
+
allow(PARSER).to receive(:load_file).and_return(settings)
|
38
|
+
provider = described_class.new "bla", namespace: namespace
|
39
|
+
expect(provider.instance_variable_get(:@settings)).to eq settings["some"]["nested"]
|
40
|
+
end
|
41
|
+
|
42
|
+
it "raises if the namespace isn't found" do
|
43
|
+
allow(PARSER).to receive(:load_file).and_return({})
|
44
|
+
expect {
|
45
|
+
silence_stderr do
|
46
|
+
described_class.new "bla", namespace: "bar"
|
47
|
+
end
|
48
|
+
}.to raise_error ArgumentError
|
49
|
+
end
|
50
|
+
|
51
|
+
it "works with an empty namespace in the file" do
|
52
|
+
allow(PARSER).to receive(:load_file).and_return("foo" => {"bar" => nil})
|
53
|
+
expect {
|
54
|
+
silence_stderr do
|
55
|
+
described_class.new "bla", namespace: "foo.bar"
|
56
|
+
end
|
57
|
+
}.to_not raise_error
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "with required set to false" do
|
62
|
+
it "doesn't raise if a file isn't found" do
|
63
|
+
allow(PARSER).to receive(:load_file).and_raise(Errno::ENOENT)
|
64
|
+
expect {
|
65
|
+
silence_stderr do
|
66
|
+
described_class.new "not_me", required: false
|
67
|
+
end
|
68
|
+
}.not_to raise_error
|
69
|
+
end
|
70
|
+
|
71
|
+
it "doesn't raise if a namespace isn't found" do
|
72
|
+
allow(PARSER).to receive(:load_file).and_return({})
|
73
|
+
expect {
|
74
|
+
silence_stderr do
|
75
|
+
described_class.new "bla", namespace: "foo", required: false
|
76
|
+
end
|
77
|
+
}.not_to raise_error
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "#lookup_path" do
|
83
|
+
before do
|
84
|
+
allow(PARSER).to receive(:load_file).and_return(settings)
|
85
|
+
@provider = described_class.new "dummy"
|
86
|
+
end
|
87
|
+
|
88
|
+
it "looks up the whole nesting" do
|
89
|
+
expect(@provider.lookup_path(%w[some nested some])).to eq settings["some"]["nested"]["some"]
|
90
|
+
end
|
91
|
+
|
92
|
+
it "returns nil if no setting is found" do
|
93
|
+
expect(@provider.lookup_path(["not_me"])).to be_nil
|
94
|
+
end
|
95
|
+
|
96
|
+
context "with raise_on_missing set to true" do
|
97
|
+
before do
|
98
|
+
@provider = described_class.new "dummy", raise_on_missing: true
|
99
|
+
end
|
100
|
+
|
101
|
+
it "looks up the whole nesting" do
|
102
|
+
expect(@provider.lookup_path(%w[some nested some])).to eq settings["some"]["nested"]["some"]
|
103
|
+
end
|
104
|
+
|
105
|
+
it "returns nil if no setting is found" do
|
106
|
+
expect {
|
107
|
+
@provider.lookup_path ["not_me"]
|
108
|
+
}.to raise_error Configurate::MissingSetting
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -1,11 +1,16 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
2
4
|
|
3
5
|
describe Configurate::Provider::YAML do
|
4
|
-
let(:settings) {
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
let(:settings) {
|
7
|
+
{
|
8
|
+
"toplevel" => "bar",
|
9
|
+
"some" => {
|
10
|
+
"nested" => {"some" => "lala", "setting" => "foo"}
|
11
|
+
}
|
12
|
+
}
|
13
|
+
}
|
9
14
|
|
10
15
|
describe "#initialize" do
|
11
16
|
it "loads the file" do
|
@@ -23,26 +28,25 @@ describe Configurate::Provider::YAML do
|
|
23
28
|
}.to raise_error Errno::ENOENT
|
24
29
|
end
|
25
30
|
|
26
|
-
|
27
31
|
context "with a namespace" do
|
28
32
|
it "looks in the file for that namespace" do
|
29
33
|
namespace = "some.nested"
|
30
34
|
allow(::YAML).to receive(:load_file).and_return(settings)
|
31
|
-
provider = described_class.new
|
32
|
-
expect(provider.instance_variable_get
|
35
|
+
provider = described_class.new "bla", namespace: namespace
|
36
|
+
expect(provider.instance_variable_get(:@settings)).to eq settings["some"]["nested"]
|
33
37
|
end
|
34
38
|
|
35
39
|
it "raises if the namespace isn't found" do
|
36
40
|
allow(::YAML).to receive(:load_file).and_return({})
|
37
41
|
expect {
|
38
|
-
described_class.new
|
39
|
-
}.to raise_error
|
42
|
+
described_class.new "bla", namespace: "bar"
|
43
|
+
}.to raise_error ArgumentError
|
40
44
|
end
|
41
45
|
|
42
46
|
it "works with an empty namespace in the file" do
|
43
|
-
allow(::YAML).to receive(:load_file).and_return(
|
47
|
+
allow(::YAML).to receive(:load_file).and_return("foo" => {"bar" => nil})
|
44
48
|
expect {
|
45
|
-
described_class.new
|
49
|
+
described_class.new "bla", namespace: "foo.bar"
|
46
50
|
}.to_not raise_error
|
47
51
|
end
|
48
52
|
end
|
@@ -51,14 +55,18 @@ describe Configurate::Provider::YAML do
|
|
51
55
|
it "doesn't raise if a file isn't found" do
|
52
56
|
allow(::YAML).to receive(:load_file).and_raise(Errno::ENOENT)
|
53
57
|
expect {
|
54
|
-
|
58
|
+
silence_stderr do
|
59
|
+
described_class.new "not_me", required: false
|
60
|
+
end
|
55
61
|
}.not_to raise_error
|
56
62
|
end
|
57
63
|
|
58
64
|
it "doesn't raise if a namespace isn't found" do
|
59
65
|
allow(::YAML).to receive(:load_file).and_return({})
|
60
66
|
expect {
|
61
|
-
|
67
|
+
silence_stderr do
|
68
|
+
described_class.new "bla", namespace: "foo", required: false
|
69
|
+
end
|
62
70
|
}.not_to raise_error
|
63
71
|
end
|
64
72
|
end
|
@@ -67,15 +75,31 @@ describe Configurate::Provider::YAML do
|
|
67
75
|
describe "#lookup_path" do
|
68
76
|
before do
|
69
77
|
allow(::YAML).to receive(:load_file).and_return(settings)
|
70
|
-
@provider = described_class.new
|
78
|
+
@provider = described_class.new "dummy"
|
71
79
|
end
|
72
80
|
|
73
81
|
it "looks up the whole nesting" do
|
74
|
-
expect(@provider.lookup_path
|
82
|
+
expect(@provider.lookup_path(%w[some nested some])).to eq settings["some"]["nested"]["some"]
|
75
83
|
end
|
76
84
|
|
77
85
|
it "returns nil if no setting is found" do
|
78
|
-
expect(@provider.lookup_path
|
86
|
+
expect(@provider.lookup_path(["not_me"])).to be_nil
|
87
|
+
end
|
88
|
+
|
89
|
+
context "with raise_on_missing set to true" do
|
90
|
+
before do
|
91
|
+
@provider = described_class.new "dummy", raise_on_missing: true
|
92
|
+
end
|
93
|
+
|
94
|
+
it "looks up the whole nesting" do
|
95
|
+
expect(@provider.lookup_path(%w[some nested some])).to eq settings["some"]["nested"]["some"]
|
96
|
+
end
|
97
|
+
|
98
|
+
it "returns nil if no setting is found" do
|
99
|
+
expect {
|
100
|
+
@provider.lookup_path ["not_me"]
|
101
|
+
}.to raise_error Configurate::MissingSetting
|
102
|
+
end
|
79
103
|
end
|
80
104
|
end
|
81
105
|
end
|
@@ -1,10 +1,12 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
2
4
|
|
3
5
|
describe Configurate::Provider::Base do
|
4
6
|
describe "#lookup" do
|
5
7
|
subject { described_class.new }
|
6
8
|
it "calls #lookup_path" do
|
7
|
-
path = Configurate::SettingPath.new([
|
9
|
+
path = Configurate::SettingPath.new(%w[foo bar])
|
8
10
|
expect(subject).to receive(:lookup_path).with(path).and_return("something")
|
9
11
|
expect(subject.lookup(path)).to eq "something"
|
10
12
|
end
|
@@ -16,4 +18,15 @@ describe Configurate::Provider::Base do
|
|
16
18
|
}.to raise_error Configurate::SettingNotFoundError
|
17
19
|
end
|
18
20
|
end
|
21
|
+
|
22
|
+
describe "::lookup_in_hash" do
|
23
|
+
let(:hash) { {foo: {bar: nil}} }
|
24
|
+
it "returns nil if key is nil" do
|
25
|
+
expect(Configurate::Provider.lookup_in_hash(%i[foo bar], hash) { :fallback }).to be_nil
|
26
|
+
end
|
27
|
+
|
28
|
+
it "returns fallback for a non-existent key" do
|
29
|
+
expect(Configurate::Provider.lookup_in_hash(%i[foo bar baz], hash) { :fallback }).to eq :fallback
|
30
|
+
end
|
31
|
+
end
|
19
32
|
end
|
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
2
4
|
|
3
5
|
describe Configurate::Proxy do
|
4
6
|
let(:lookup_chain) { double(lookup: "something") }
|
@@ -6,12 +8,12 @@ describe Configurate::Proxy do
|
|
6
8
|
|
7
9
|
describe "in case statements" do
|
8
10
|
it "acts like the target" do
|
9
|
-
pending "If anyone knows a way to overwrite
|
11
|
+
pending "If anyone knows a sane way to overwrite Module#===, please tell me :P"
|
10
12
|
result = case proxy
|
11
13
|
when String
|
12
|
-
|
14
|
+
"string"
|
13
15
|
else
|
14
|
-
|
16
|
+
"wrong"
|
15
17
|
end
|
16
18
|
expect(result).to eq "string"
|
17
19
|
end
|
@@ -23,6 +25,11 @@ describe Configurate::Proxy do
|
|
23
25
|
proxy.method_missing(:enable?)
|
24
26
|
end
|
25
27
|
|
28
|
+
it "calls #target if the method ends with a !" do
|
29
|
+
expect(lookup_chain).to receive(:lookup).and_return(false)
|
30
|
+
proxy.method_missing(:do_it!)
|
31
|
+
end
|
32
|
+
|
26
33
|
it "calls #target if the method ends with a =" do
|
27
34
|
expect(lookup_chain).to receive(:lookup).and_return(false)
|
28
35
|
proxy.method_missing(:url=)
|
@@ -49,9 +56,8 @@ describe Configurate::Proxy do
|
|
49
56
|
end
|
50
57
|
|
51
58
|
describe "#target" do
|
52
|
-
[
|
53
|
-
|
54
|
-
:start_with?, :end_with?].each do |method|
|
59
|
+
%i[to_s to_xml respond_to? present? != eql? each try size length
|
60
|
+
count == =~ gsub blank? chop start_with? end_with?].each do |method|
|
55
61
|
it "is called for accessing #{method} on the proxy" do
|
56
62
|
target = double(respond_to?: true, _proxy?: false)
|
57
63
|
allow(lookup_chain).to receive(:lookup).and_return(target)
|
@@ -72,5 +78,25 @@ describe Configurate::Proxy do
|
|
72
78
|
it "returns nil if no setting is given" do
|
73
79
|
expect(proxy.target).to be_nil
|
74
80
|
end
|
81
|
+
|
82
|
+
it "converts to a string" do
|
83
|
+
allow(lookup_chain).to receive(:lookup).and_return("bar")
|
84
|
+
expect("foo#{proxy.something}").to eq "foobar"
|
85
|
+
end
|
86
|
+
|
87
|
+
it "converts to a number" do
|
88
|
+
allow(lookup_chain).to receive(:lookup).and_return(1)
|
89
|
+
expect(2 + proxy.something).to eq 3
|
90
|
+
end
|
91
|
+
|
92
|
+
it "converts to an array" do
|
93
|
+
allow(lookup_chain).to receive(:lookup).and_return([1, 2])
|
94
|
+
expect(%i[a b].zip(proxy.something)).to eq [[:a, 1], [:b, 2]]
|
95
|
+
end
|
96
|
+
|
97
|
+
it "converts to a hash" do
|
98
|
+
allow(lookup_chain).to receive(:lookup).and_return(a: :b)
|
99
|
+
expect({c: :d}.merge(proxy.something)).to eq a: :b, c: :d
|
100
|
+
end
|
75
101
|
end
|
76
102
|
end
|