configurate 0.3.1 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: ce3f9cd0e402209f0d1f6658072604e926a0553b
4
- data.tar.gz: 685a8812aebdcad989056ffe75d6d9ecff65d7f6
2
+ SHA256:
3
+ metadata.gz: c7ee31139c43b2f17023d605dee685f0618fcc0e56b068733cddb8e5e10cf006
4
+ data.tar.gz: 5ee1c764538c194795750718c6a530cbd94684d334782afc7fa47a35083547af
5
5
  SHA512:
6
- metadata.gz: c7b64517e364ae891790d10737deb7feadcb326eb650d6f5b8dcf05628a5e8d99073d939e05fcf8fb75a5874043751c32b47c859adece475b16b56c050c08993
7
- data.tar.gz: 7ddc889f275b59ca061289392deb07bda601c28520b5957168470b1bcf9efc33e012db50b648a642e3a4fe3552ccb633eabc0d336e30374a54e2a880744ff2b7
6
+ metadata.gz: c221bc2ed5cf3b7705a207776628621301cd73c3e891dac13ba9d2ada574fc265a5678edff29974da657daa373d712ccb6753ee2083ad6ab0d94b36cd1314225
7
+ data.tar.gz: 338aaf220e3ccc945a35079fb15c50c6af87132c78c97fb7fe0ff1d2d8bdd54e5a0406aa01d890eb910cfee55fb649667e67c042c54e005d0772ce654ba9be1a
@@ -1,3 +1,9 @@
1
+ # 0.4.0
2
+
3
+ * `Configurate::Proxy` returns its own singleton class if the target does not support creating one.
4
+ * Extract `Configurate::Provider::StringHash` as a new base class for hash based providers.
5
+ * Add `Configurate::Provider::TOML`.
6
+
1
7
  # 0.3.1
2
8
 
3
9
  * Configurate::Provider::Dynamic returns true when passed the special
data/README.md CHANGED
@@ -1,8 +1,7 @@
1
1
  # Configurate - A flexible configuration system
2
- [![Gem Version](https://badge.fury.io/rb/configurate.png)](https://rubygems.org/gems/configurate)
3
- [![Build Status](https://secure.travis-ci.org/jhass/configurate.png?branch=master)](https://travis-ci.org/jhass/configurate)
4
- [![Gemnasium](https://gemnasium.com/jhass/configurate.png)](https://gemnasium.com/jhass/configurate)
5
- [![Code Climate](https://codeclimate.com/github/jhass/configurate.png)](https://codeclimate.com/github/jhass/configurate)
2
+ [![Gem Version](https://badge.fury.io/rb/configurate.svg)](https://badge.fury.io/rb/configurate)
3
+ [![Build Status](https://travis-ci.org/jhass/configurate.svg?branch=master)](https://travis-ci.org/jhass/configurate)
4
+ [![Code Climate](https://codeclimate.com/github/jhass/configurate.svg)](https://codeclimate.com/github/jhass/configurate)
6
5
  [![Coverage Status](https://coveralls.io/repos/jhass/configurate/badge.svg?branch=master)](https://coveralls.io/r/jhass/configurate?branch=master)
7
6
 
8
7
  Configurate allows you to specify a chain of configuration providers which are
@@ -107,14 +106,6 @@ will always output `unknown`. Again use `.get`
107
106
 
108
107
  ## Shipped providers
109
108
 
110
- ### Configurate::Provider::Base
111
-
112
- A convenience base class changing the interface for implementers. It provides a basic `#lookup` method
113
- which just passes all parameters through to `#lookup_path`.
114
- The result of `#lookup_path` is returned, unless it's `nil`
115
- then `Configurate::SettingNotFoundError` is raised. Subclasses are expected to implement `#lookup_path`.
116
- Do not use this class directly as a provider!
117
-
118
109
  ### Configurate::Provider::Env
119
110
 
120
111
  This class transforms a query string into a name for a environment variable and looks up this variable then.
@@ -124,6 +115,40 @@ into arrays.
124
115
 
125
116
  This provider does not take any additional initialization parameters.
126
117
 
118
+ ### Configurate::Provider::TOML
119
+
120
+ This provider reads settings from a given [TOML](https://github.com/toml-lang/toml) file. It converts the sections of
121
+ query string to a nested value. For a given TOML file
122
+
123
+ ```toml
124
+ [stuff]
125
+ enable = true
126
+ param = "foo"
127
+
128
+ [stuff.nested]
129
+ param = "bar"
130
+ ```
131
+
132
+ the following queries would be valid:
133
+
134
+ ```ruby
135
+ Config.stuff.enable? # => true
136
+ Config.stuff.param # => "foo"
137
+ Config.stuff.nested.param # => "bar"
138
+ ```
139
+
140
+ This provider depends on the [tomlrb](https://github.com/fbernier/tomlrb) gem. This is why it is not loaded by default and
141
+ needs an explicit `require 'configurate/provider/toml' to be available.
142
+
143
+ The initializer takes a path to the configuration file a the mandatory first argument and
144
+ the following optional parameters:
145
+
146
+ * *namespace:* Specify a alternative root. This is useful if you for example add the same file multiple
147
+ times through multiple providers, with different namespaces, letting you override settings depending on
148
+ the rails environment, without duplicating common settings. Defaults to none.
149
+ * *required:* Whether to raise an error if the the file isn't found or, if one is given, the namespace
150
+ doesn't exist in the file.
151
+
127
152
  ### Configurate::Provider::YAML
128
153
 
129
154
  This provider reads settings from a given [YAML](http://www.yaml.org) file. It converts the sections of
@@ -145,8 +170,8 @@ Config.stuff.param # => "foo"
145
170
  Config.stuff.nested.param # => "bar"
146
171
  ```
147
172
 
148
- The initializer takes a path to the configuration file as mandatory first argument and
149
- the following optional parameters, as a hash:
173
+ The initializer takes a path to the configuration file a the mandatory first argument and
174
+ the following optional parameters:
150
175
 
151
176
  * *namespace:* Specify a alternative root. This is useful if you for example add the same file multiple
152
177
  times through multiple providers, with different namespaces, letting you override settings depending on
@@ -154,6 +179,46 @@ the following optional parameters, as a hash:
154
179
  * *required:* Whether to raise an error if the the file isn't found or, if one is given, the namespace
155
180
  doesn't exist in the file.
156
181
 
182
+
183
+ ### Configurate::Provider::StringHash
184
+
185
+ A provider taking a (nested) `Hash` where all keys are strings. The query string is then looked up in this hash.
186
+
187
+ So for a given `Hash`
188
+
189
+ ```ruby
190
+ {
191
+ "stuff" => {
192
+ "enable" => true,
193
+ "param" => "foo",
194
+ "nested" => {
195
+ "param" => "bar"
196
+ }
197
+ }
198
+ }
199
+ ```
200
+
201
+ the following queries would be valid:
202
+
203
+ ```ruby
204
+ Config.stuff.enable? # => true
205
+ Config.stuff.param # => "foo"
206
+ Config.stuff.nested.param # => "bar"
207
+ ```
208
+
209
+ The initializer takes the hash as the mandatory first argument and
210
+ the following optional parameters:
211
+
212
+ * *namespace:* Specify a alternative root. This is useful if you for example add the same file multiple
213
+ times through multiple providers, with different namespaces, letting you override settings depending on
214
+ the rails environment, without duplicating common settings. Defaults to none.
215
+ * *required:* Whether to raise an error if the namespace
216
+ doesn't exist in the hash.
217
+ * *source:* A hint text about the origin of the configuration data to be used in error messages.
218
+
219
+ As you may have noticed by now, `Configurate::Provider::YAML` and `Configurate::Provider::TOML` are merely convenience
220
+ subclasses of this provider, loading the file for you.
221
+
157
222
  ### Configurate::Provider::Dynamic
158
223
 
159
224
  A provider which stores the first additional parameter if the query string ends with an equal sign and can
@@ -167,6 +232,14 @@ Config.reset_dynamic!
167
232
  Config.foo.bar # => nil
168
233
  ```
169
234
 
235
+ ### Configurate::Provider::Base
236
+
237
+ A convenience base class changing the interface for implementers. It provides a basic `#lookup` method
238
+ which just passes all parameters through to `#lookup_path`.
239
+ The result of `#lookup_path` is returned, unless it's `nil`
240
+ then `Configurate::SettingNotFoundError` is raised. Subclasses are expected to implement `#lookup_path`.
241
+ Do not use this class directly as a provider!
242
+
170
243
  ## Writing a provider
171
244
 
172
245
  ...should be pretty easy. For example here is the `Configurate::Provider::Env` provider:
@@ -184,6 +257,8 @@ class Configurate::Provider::Env < Configurate::Provider::Base
184
257
  end
185
258
  ```
186
259
 
260
+ `Configurate::Provider::StringHash` should also serve as a useful baseclass for most providers.
261
+
187
262
 
188
263
  ## Documentation
189
264
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "forwardable"
2
4
 
3
5
  require "configurate/setting_path"
@@ -57,10 +59,14 @@ module Configurate
57
59
 
58
60
  def_delegators :@lookup_chain, :lookup, :add_provider, :[]
59
61
 
62
+ # rubocop:disable Style/MethodMissingSuper we handle all calls
63
+ # rubocop:disable Style/MissingRespondToMissing we override respond_to? instead
64
+
60
65
  # See description and {#lookup}, {#[]} and {#add_provider}
61
66
  def method_missing(method, *args, &block)
62
67
  Proxy.new(@lookup_chain).public_send(method, *args, &block)
63
68
  end
69
+ # rubocop:enable all
64
70
 
65
71
  # Create a new configuration object
66
72
  # @yield the given block will be evaluated in the context of the new object
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Configurate
2
4
  # This object builds a chain of configuration providers to try to find
3
5
  # the value of a setting.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Configurate
2
4
  module Provider
3
5
  # This provides a basic {#lookup} method for other providers to build
@@ -9,6 +11,7 @@ module Configurate
9
11
  def lookup(*args)
10
12
  result = lookup_path(*args)
11
13
  return result unless result.nil?
14
+
12
15
  raise Configurate::SettingNotFoundError, "The setting #{args.first} was not found"
13
16
  end
14
17
  end
@@ -24,11 +27,13 @@ module Configurate
24
27
  hash = hash[setting_path.shift]
25
28
  end
26
29
  return fallback.call unless setting_path.empty?
30
+
27
31
  hash
28
32
  end
29
33
  end
30
34
  end
31
35
 
36
+ require "configurate/provider/string_hash"
32
37
  require "configurate/provider/yaml"
33
38
  require "configurate/provider/env"
34
39
  require "configurate/provider/dynamic"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Configurate
2
4
  module Provider
3
5
  # This provider knows nothing upon initialization, however if you access
@@ -13,7 +15,7 @@ module Configurate
13
15
  return true
14
16
  end
15
17
 
16
- if setting_path.setter? && args.length > 0
18
+ if setting_path.setter? && !args.empty?
17
19
  *root, key = setting_path.to_a
18
20
  hash = root.inject(settings) {|hash, key| hash[key] }
19
21
  hash[key] = extract_value(args)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Configurate
2
4
  module Provider
3
5
  # This provider looks for settings in the environment.
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Configurate
4
+ module Provider
5
+ # This provider takes a nested string keyed hash and does nested lookups in it.
6
+ class StringHash < Base
7
+ # @param hash [::Hash] the string keyed hash to provide values from
8
+ # @param namespace [String] optionally set this as the root
9
+ # @param required [Boolean] whether or not to raise an error if
10
+ # the namespace, if given, is not found. Defaults to +true+.
11
+ # @param raise_on_missing [Boolean] whether to raise {Configurate::MissingSetting}
12
+ # if a setting can't be provided. Defaults to +false+.
13
+ # @param source [String] optional hint of what's the source of this configuration. Used in error messages.
14
+ # @raise [ArgumentError] if the namespace isn't found in the hash or the given object is not a hash
15
+ def initialize hash, namespace: nil, required: true, raise_on_missing: false, source: nil
16
+ raise ArgumentError, "Please provide a hash" unless hash.is_a?(Hash)
17
+
18
+ @required = required
19
+ @raise_on_missing = raise_on_missing
20
+ @source = source
21
+ @settings = root_from hash, namespace
22
+ end
23
+
24
+ def lookup_path setting_path, *_
25
+ Provider.lookup_in_hash(setting_path, @settings) {
26
+ raise MissingSetting.new "#{setting_path} is not a valid setting." if @raise_on_missing
27
+
28
+ nil
29
+ }
30
+ end
31
+
32
+ private
33
+
34
+ def root_from hash, namespace
35
+ return hash if namespace.nil?
36
+
37
+ Provider.lookup_in_hash(SettingPath.new(namespace), hash) do
38
+ raise ArgumentError, "Namespace #{namespace} not found #{"in #{@source}" if @source}" if @required
39
+
40
+ warn "WARNING: Namespace #{namespace} not found #{"in #{@source}" if @source}"
41
+ nil
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "configurate"
4
+ require "tomlrb"
5
+
6
+ module Configurate
7
+ module Provider
8
+ # This provider tries to open a TOML file and does nested lookups
9
+ # in it.
10
+ class TOML < StringHash
11
+ # @param file [String] the path to the file
12
+ # @param namespace [String] optionally set this as the root
13
+ # @param required [Boolean] whether or not to raise an error if
14
+ # the file or the namespace, if given, is not found. Defaults to +true+.
15
+ # @param raise_on_missing [Boolean] whether to raise {Configurate::MissingSetting}
16
+ # if a setting can't be provided. Defaults to +false+.
17
+ # @raise [ArgumentError] if the namespace isn't found in the file
18
+ # @raise [Errno:ENOENT] if the file isn't found
19
+ def initialize file, namespace: nil, required: true, raise_on_missing: false
20
+ super(Tomlrb.load_file(file),
21
+ namespace: namespace,
22
+ required: required,
23
+ raise_on_missing: raise_on_missing,
24
+ source: file
25
+ )
26
+ rescue Errno::ENOENT => e
27
+ warn "WARNING: Configuration file #{file} not found, ensure it's present"
28
+ raise e if required
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "yaml"
2
4
 
3
5
  module Configurate
4
6
  module Provider
5
7
  # This provider tries to open a YAML file and does nested lookups
6
8
  # in it.
7
- class YAML < Base
9
+ class YAML < StringHash
8
10
  # @param file [String] the path to the file
9
11
  # @param namespace [String] optionally set this as the root
10
12
  # @param required [Boolean] whether or not to raise an error if
@@ -14,29 +16,16 @@ module Configurate
14
16
  # @raise [ArgumentError] if the namespace isn't found in the file
15
17
  # @raise [Errno:ENOENT] if the file isn't found
16
18
  def initialize file, namespace: nil, required: true, raise_on_missing: false
17
- @raise_on_missing = raise_on_missing
18
- @settings = {}
19
-
20
- @settings = ::YAML.load_file(file)
21
-
22
- unless namespace.nil?
23
- @settings = Provider.lookup_in_hash(SettingPath.new(namespace), @settings) do
24
- raise ArgumentError, "Namespace #{namespace} not found in #{file}" if required
25
- $stderr.puts "WARNING: Namespace #{namespace} not found in #{file}"
26
- nil
27
- end
28
- end
19
+ super(::YAML.load_file(file),
20
+ namespace: namespace,
21
+ required: required,
22
+ raise_on_missing: raise_on_missing,
23
+ source: file
24
+ )
29
25
  rescue Errno::ENOENT => e
30
26
  warn "WARNING: Configuration file #{file} not found, ensure it's present"
31
27
  raise e if required
32
28
  end
33
-
34
- def lookup_path setting_path, *_
35
- Provider.lookup_in_hash(setting_path, @settings) {
36
- raise MissingSetting.new "#{setting_path} is not a valid setting." if @raise_on_missing
37
- nil
38
- }
39
- end
40
29
  end
41
30
  end
42
31
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Configurate
2
4
  # Proxy object to support nested settings
3
5
  #
@@ -23,7 +25,7 @@ module Configurate
23
25
  !target
24
26
  end
25
27
 
26
- %i(!= == eql? coerce).each do |method|
28
+ %i[!= == eql? coerce].each do |method|
27
29
  define_method method do |other|
28
30
  target.public_send method, target_or_object(other)
29
31
  end
@@ -38,6 +40,7 @@ module Configurate
38
40
  define_method method do
39
41
  value = target
40
42
  return value.public_send converter if value.respond_to? converter
43
+
41
44
  value.public_send method
42
45
  end
43
46
  end
@@ -55,6 +58,17 @@ module Configurate
55
58
  end
56
59
  alias_method :public_send, :send
57
60
 
61
+ def singleton_class
62
+ target.singleton_class
63
+ rescue ::TypeError
64
+ class << self
65
+ self
66
+ end
67
+ end
68
+
69
+ # rubocop:disable Style/MethodMissingSuper we handle all calls
70
+ # rubocop:disable Style/MissingRespondToMissing we override respond_to? instead
71
+
58
72
  def method_missing setting, *args, &block
59
73
  return target.public_send(setting, *args, &block) if target_respond_to? setting
60
74
 
@@ -64,6 +78,7 @@ module Configurate
64
78
 
65
79
  self
66
80
  end
81
+ # rubocop:enable all
67
82
 
68
83
  # Get the setting at the current path, if found.
69
84
  # (see LookupChain#lookup)
@@ -76,7 +91,7 @@ module Configurate
76
91
 
77
92
  private
78
93
 
79
- COMMON_KEY_NAMES = %i(key method)
94
+ COMMON_KEY_NAMES = %i[key method].freeze
80
95
 
81
96
  def target_respond_to? setting, include_private=false
82
97
  return false if COMMON_KEY_NAMES.include? setting
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "forwardable"
2
4
 
3
5
  module Configurate
@@ -40,18 +42,19 @@ module Configurate
40
42
 
41
43
  def each
42
44
  return to_enum(:each) unless block_given?
45
+
43
46
  @path.each do |component|
44
47
  yield clean_special_characters(component)
45
48
  end
46
49
  end
47
50
 
48
- %i(join first last shift pop).each do |method|
51
+ %i[join first last shift pop].each do |method|
49
52
  define_method method do |*args|
50
53
  clean_special_characters @path.public_send(method, *args)
51
54
  end
52
55
  end
53
56
 
54
- %i(<< unshift push).each do |method|
57
+ %i[<< unshift push].each do |method|
55
58
  define_method method do |*args|
56
59
  @path.public_send method, *args.map(&:to_s)
57
60
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "spec_helper"
2
4
 
3
5
  class InvalidConfigurationProvider; end
@@ -71,34 +73,34 @@ describe Configurate::LookupChain do
71
73
 
72
74
  it "converts numbers to strings" do
73
75
  allow(@provider[0]).to receive(:lookup).and_return(5)
74
- expect(subject.lookup "foo").to eq "5"
76
+ expect(subject.lookup("foo")).to eq "5"
75
77
  end
76
78
 
77
79
  it "does not convert false to a string" do
78
80
  allow(@provider[0]).to receive(:lookup).and_return(false)
79
- expect(subject.lookup "enable").to be_falsey
81
+ expect(subject.lookup("enable")).to be_falsey
80
82
  end
81
83
 
82
84
  it "converts 'true' to true" do
83
85
  allow(@provider[0]).to receive(:lookup).and_return("true")
84
- expect(subject.lookup "enable").to be_truthy
86
+ expect(subject.lookup("enable")).to be_truthy
85
87
  end
86
88
 
87
89
  it "converts 'false' to false" do
88
90
  allow(@provider[0]).to receive(:lookup).and_return("false")
89
- expect(subject.lookup "enable").to be_falsey
91
+ expect(subject.lookup("enable")).to be_falsey
90
92
  end
91
93
 
92
94
  it "returns the value unchanged if it can't be converted" do
93
95
  value = double
94
96
  allow(value).to receive(:respond_to?).with(:to_s).and_return(false)
95
97
  allow(@provider[0]).to receive(:lookup).and_return(value)
96
- expect(subject.lookup "enable").to eq value
98
+ expect(subject.lookup("enable")).to eq value
97
99
  end
98
100
 
99
101
  it "returns nil if no value is found" do
100
102
  @provider.each {|p| allow(p).to receive(:lookup).and_raise(Configurate::SettingNotFoundError) }
101
- expect(subject.lookup "not.me").to be_nil
103
+ expect(subject.lookup("not.me")).to be_nil
102
104
  end
103
105
  end
104
106
  end
@@ -1,16 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
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 Configurate::SettingPath.new(["not_me"])).to be_nil
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 Configurate::SettingPath.new(%w(find_me later))).to eq "there"
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,14 +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(%w(find_me later=)), "a" => "b"
24
- expect(subject.lookup_path Configurate::SettingPath.new(%w(find_me later a))).to eq "b"
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"
25
27
  end
26
28
 
27
29
  it "clears out all overrides on reset_dynamic!" do
28
30
  subject.lookup_path Configurate::SettingPath.new(["find_me", "later="]), "there"
29
- expect(subject.lookup_path Configurate::SettingPath.new(["reset_dynamic!"])).to eq true
30
- expect(subject.lookup_path Configurate::SettingPath.new(%w(find_me later))).to_not eq "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"
31
33
  end
32
34
  end
33
35
  end
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "spec_helper"
2
4
 
3
5
  describe Configurate::Provider::Env do
4
6
  subject { described_class.new }
5
- let(:existing_path) { %w(existing setting) }
6
- let(:not_existing_path) { %w(not existing path) }
7
+ let(:existing_path) { %w[existing setting] }
8
+ let(:not_existing_path) { %w[not existing path] }
7
9
  let(:array_path) { ["array"] }
8
10
  before(:all) do
9
11
  ENV["EXISTING_SETTING"] = "there"
@@ -22,11 +24,11 @@ describe Configurate::Provider::Env do
22
24
  end
23
25
 
24
26
  it "returns nil if the setting isn't available" do
25
- expect(subject.lookup_path not_existing_path).to be_nil
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 array_path).to eq %w(foo bar baz)
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,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+ require "configurate/provider/toml"
5
+
6
+ describe Configurate::Provider::TOML do
7
+ let(:settings) {
8
+ {
9
+ "toplevel" => "bar",
10
+ "some" => {
11
+ "nested" => {"some" => "lala", "setting" => "foo"}
12
+ }
13
+ }
14
+ }
15
+
16
+ describe "#initialize" do
17
+ it "loads the file" do
18
+ file = "foobar.toml"
19
+ expect(Tomlrb).to receive(:load_file).with(file).and_return({})
20
+ described_class.new file
21
+ end
22
+
23
+ it "raises if the file is not found" do
24
+ allow(Tomlrb).to receive(:load_file).and_raise(Errno::ENOENT)
25
+ expect {
26
+ silence_stderr do
27
+ described_class.new "foo"
28
+ end
29
+ }.to raise_error Errno::ENOENT
30
+ end
31
+
32
+ context "with a namespace" do
33
+ it "looks in the file for that namespace" do
34
+ namespace = "some.nested"
35
+ allow(Tomlrb).to receive(:load_file).and_return(settings)
36
+ provider = described_class.new "bla", namespace: namespace
37
+ expect(provider.instance_variable_get(:@settings)).to eq settings["some"]["nested"]
38
+ end
39
+
40
+ it "raises if the namespace isn't found" do
41
+ allow(Tomlrb).to receive(:load_file).and_return({})
42
+ expect {
43
+ silence_stderr do
44
+ described_class.new "bla", namespace: "bar"
45
+ end
46
+ }.to raise_error ArgumentError
47
+ end
48
+
49
+ it "works with an empty namespace in the file" do
50
+ allow(Tomlrb).to receive(:load_file).and_return("foo" => {"bar" => nil})
51
+ expect {
52
+ silence_stderr do
53
+ described_class.new "bla", namespace: "foo.bar"
54
+ end
55
+ }.to_not raise_error
56
+ end
57
+ end
58
+
59
+ context "with required set to false" do
60
+ it "doesn't raise if a file isn't found" do
61
+ allow(Tomlrb).to receive(:load_file).and_raise(Errno::ENOENT)
62
+ expect {
63
+ silence_stderr do
64
+ described_class.new "not_me", required: false
65
+ end
66
+ }.not_to raise_error
67
+ end
68
+
69
+ it "doesn't raise if a namespace isn't found" do
70
+ allow(Tomlrb).to receive(:load_file).and_return({})
71
+ expect {
72
+ silence_stderr do
73
+ described_class.new "bla", namespace: "foo", required: false
74
+ end
75
+ }.not_to raise_error
76
+ end
77
+ end
78
+ end
79
+
80
+ describe "#lookup_path" do
81
+ before do
82
+ allow(Tomlrb).to receive(:load_file).and_return(settings)
83
+ @provider = described_class.new "dummy"
84
+ end
85
+
86
+ it "looks up the whole nesting" do
87
+ expect(@provider.lookup_path(%w[some nested some])).to eq settings["some"]["nested"]["some"]
88
+ end
89
+
90
+ it "returns nil if no setting is found" do
91
+ expect(@provider.lookup_path(["not_me"])).to be_nil
92
+ end
93
+
94
+ context "with raise_on_missing set to true" do
95
+ before do
96
+ @provider = described_class.new "dummy", raise_on_missing: true
97
+ end
98
+
99
+ it "looks up the whole nesting" do
100
+ expect(@provider.lookup_path(%w[some nested some])).to eq settings["some"]["nested"]["some"]
101
+ end
102
+
103
+ it "returns nil if no setting is found" do
104
+ expect {
105
+ @provider.lookup_path ["not_me"]
106
+ }.to raise_error Configurate::MissingSetting
107
+ end
108
+ end
109
+ end
110
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "spec_helper"
2
4
 
3
5
  describe Configurate::Provider::YAML do
@@ -31,14 +33,14 @@ describe Configurate::Provider::YAML do
31
33
  namespace = "some.nested"
32
34
  allow(::YAML).to receive(:load_file).and_return(settings)
33
35
  provider = described_class.new "bla", namespace: namespace
34
- expect(provider.instance_variable_get :@settings).to eq settings["some"]["nested"]
36
+ expect(provider.instance_variable_get(:@settings)).to eq settings["some"]["nested"]
35
37
  end
36
38
 
37
39
  it "raises if the namespace isn't found" do
38
40
  allow(::YAML).to receive(:load_file).and_return({})
39
41
  expect {
40
42
  described_class.new "bla", namespace: "bar"
41
- }.to raise_error
43
+ }.to raise_error ArgumentError
42
44
  end
43
45
 
44
46
  it "works with an empty namespace in the file" do
@@ -53,14 +55,18 @@ describe Configurate::Provider::YAML do
53
55
  it "doesn't raise if a file isn't found" do
54
56
  allow(::YAML).to receive(:load_file).and_raise(Errno::ENOENT)
55
57
  expect {
56
- described_class.new "not_me", required: false
58
+ silence_stderr do
59
+ described_class.new "not_me", required: false
60
+ end
57
61
  }.not_to raise_error
58
62
  end
59
63
 
60
64
  it "doesn't raise if a namespace isn't found" do
61
65
  allow(::YAML).to receive(:load_file).and_return({})
62
66
  expect {
63
- described_class.new "bla", namespace: "foo", required: false
67
+ silence_stderr do
68
+ described_class.new "bla", namespace: "foo", required: false
69
+ end
64
70
  }.not_to raise_error
65
71
  end
66
72
  end
@@ -73,11 +79,11 @@ describe Configurate::Provider::YAML do
73
79
  end
74
80
 
75
81
  it "looks up the whole nesting" do
76
- expect(@provider.lookup_path %w(some nested some)).to eq settings["some"]["nested"]["some"]
82
+ expect(@provider.lookup_path(%w[some nested some])).to eq settings["some"]["nested"]["some"]
77
83
  end
78
84
 
79
85
  it "returns nil if no setting is found" do
80
- expect(@provider.lookup_path ["not_me"]).to be_nil
86
+ expect(@provider.lookup_path(["not_me"])).to be_nil
81
87
  end
82
88
 
83
89
  context "with raise_on_missing set to true" do
@@ -86,7 +92,7 @@ describe Configurate::Provider::YAML do
86
92
  end
87
93
 
88
94
  it "looks up the whole nesting" do
89
- expect(@provider.lookup_path %w(some nested some)).to eq settings["some"]["nested"]["some"]
95
+ expect(@provider.lookup_path(%w[some nested some])).to eq settings["some"]["nested"]["some"]
90
96
  end
91
97
 
92
98
  it "returns nil if no setting is found" do
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
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(%w(foo bar))
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
@@ -15,17 +17,16 @@ describe Configurate::Provider::Base do
15
17
  subject.lookup("bla")
16
18
  }.to raise_error Configurate::SettingNotFoundError
17
19
  end
18
-
19
20
  end
20
21
 
21
22
  describe "::lookup_in_hash" do
22
23
  let(:hash) { {foo: {bar: nil}} }
23
24
  it "returns nil if key is nil" do
24
- expect(Configurate::Provider.lookup_in_hash(%i(foo bar), hash) { :fallback }).to be_nil
25
+ expect(Configurate::Provider.lookup_in_hash(%i[foo bar], hash) { :fallback }).to be_nil
25
26
  end
26
27
 
27
28
  it "returns fallback for a non-existent key" do
28
- expect(Configurate::Provider.lookup_in_hash(%i(foo bar baz), hash) { :fallback }).to eq :fallback
29
+ expect(Configurate::Provider.lookup_in_hash(%i[foo bar baz], hash) { :fallback }).to eq :fallback
29
30
  end
30
31
  end
31
32
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "spec_helper"
2
4
 
3
5
  describe Configurate::Proxy do
@@ -54,8 +56,8 @@ describe Configurate::Proxy do
54
56
  end
55
57
 
56
58
  describe "#target" do
57
- %i(to_s to_xml respond_to? present? != eql? each try size length
58
- count == =~ gsub blank? chop 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|
59
61
  it "is called for accessing #{method} on the proxy" do
60
62
  target = double(respond_to?: true, _proxy?: false)
61
63
  allow(lookup_chain).to receive(:lookup).and_return(target)
@@ -89,7 +91,7 @@ describe Configurate::Proxy do
89
91
 
90
92
  it "converts to an array" do
91
93
  allow(lookup_chain).to receive(:lookup).and_return([1, 2])
92
- expect(%i(a b).zip(proxy.something)).to eq [[:a, 1], [:b, 2]]
94
+ expect(%i[a b].zip(proxy.something)).to eq [[:a, 1], [:b, 2]]
93
95
  end
94
96
 
95
97
  it "converts to a hash" do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "spec_helper"
2
4
 
3
5
  describe Configurate::SettingPath do
@@ -10,7 +12,7 @@ describe Configurate::SettingPath do
10
12
  describe "#initialize" do
11
13
  context "with a string" do
12
14
  it "creates a path" do
13
- expect(described_class.new long_path.to_s).to eq long_path
15
+ expect(described_class.new(long_path.to_s)).to eq long_path
14
16
  end
15
17
  end
16
18
  end
@@ -53,7 +55,7 @@ describe Configurate::SettingPath do
53
55
 
54
56
  describe "#initialize_copy" do
55
57
  it "modifying a copy leaves the original unchanged" do
56
- original = described_class.new %w(foo bar)
58
+ original = described_class.new %w[foo bar]
57
59
  copy = original.clone
58
60
  copy << "baz"
59
61
  expect(copy).to include "baz"
@@ -89,14 +91,14 @@ describe Configurate::SettingPath do
89
91
  end
90
92
  end
91
93
 
92
- %i(join first last shift pop).each do |method|
94
+ %i[join first last shift pop].each do |method|
93
95
  describe "##{method}" do
94
96
  subject { question_path.public_send method }
95
97
  it { should_not include "?" }
96
98
  end
97
99
  end
98
100
 
99
- %i(<< unshift push).each do |method|
101
+ %i[<< unshift push].each do |method|
100
102
  describe "##{method}" do
101
103
  it "converts the argument to a string" do
102
104
  arg = double
@@ -119,7 +121,7 @@ describe Configurate::SettingPath do
119
121
 
120
122
  describe "#inspect" do
121
123
  it "includes the dotted path" do
122
- path = described_class.new(%i(foo bar))
124
+ path = described_class.new(%i[foo bar])
123
125
  expect(path.inspect).to include "foo.bar"
124
126
  end
125
127
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "spec_helper"
2
4
 
3
5
  describe Configurate::Settings do
@@ -13,7 +15,7 @@ describe Configurate::Settings do
13
15
  end
14
16
 
15
17
  %i(lookup add_provider []).each do |method|
16
- describe "#{method}" do
18
+ describe method.to_s do
17
19
  subject { described_class.create }
18
20
 
19
21
  it "delegates the call to #lookup_chain" do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file was generated by the `rspec --init` command. Conventionally, all
2
4
  # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
5
  # Require this file using `require "spec_helper"` to ensure that it is only
@@ -8,13 +10,15 @@
8
10
  begin
9
11
  require "coveralls"
10
12
  Coveralls.wear!
11
- rescue LoadError; end
13
+ rescue LoadError
14
+ end
12
15
 
13
16
  require "configurate"
14
17
 
15
18
  def silence_stderr
16
19
  $stderr = StringIO.new
17
20
  yield
21
+ ensure
18
22
  $stderr = STDERR
19
23
  end
20
24
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: configurate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonne Haß
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-06 00:00:00.000000000 Z
11
+ date: 2020-04-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '3.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: tomlrb
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 1.3.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 1.3.0
41
55
  description: Configurate is a flexible configuration system that can read settings
42
56
  from multiple sources at the same time.
43
57
  email: me@jhass.eu
@@ -53,12 +67,16 @@ files:
53
67
  - lib/configurate/provider.rb
54
68
  - lib/configurate/provider/dynamic.rb
55
69
  - lib/configurate/provider/env.rb
70
+ - lib/configurate/provider/string_hash.rb
71
+ - lib/configurate/provider/toml.rb
56
72
  - lib/configurate/provider/yaml.rb
57
73
  - lib/configurate/proxy.rb
58
74
  - lib/configurate/setting_path.rb
59
75
  - spec/configurate/lookup_chain_spec.rb
60
76
  - spec/configurate/provider/dynamic_spec.rb
61
77
  - spec/configurate/provider/env_spec.rb
78
+ - spec/configurate/provider/string_hash_spec.rb
79
+ - spec/configurate/provider/toml_spec.rb
62
80
  - spec/configurate/provider/yaml_spec.rb
63
81
  - spec/configurate/provider_spec.rb
64
82
  - spec/configurate/proxy_spec.rb
@@ -77,26 +95,26 @@ required_ruby_version: !ruby/object:Gem::Requirement
77
95
  requirements:
78
96
  - - ">="
79
97
  - !ruby/object:Gem::Version
80
- version: 1.9.2
98
+ version: 2.0.0
81
99
  required_rubygems_version: !ruby/object:Gem::Requirement
82
100
  requirements:
83
101
  - - ">="
84
102
  - !ruby/object:Gem::Version
85
103
  version: '0'
86
104
  requirements: []
87
- rubyforge_project:
88
- rubygems_version: 2.4.5
105
+ rubygems_version: 3.1.2
89
106
  signing_key:
90
107
  specification_version: 4
91
108
  summary: Flexbile configuration system
92
109
  test_files:
110
+ - spec/spec_helper.rb
111
+ - spec/configurate/lookup_chain_spec.rb
112
+ - spec/configurate/provider/toml_spec.rb
93
113
  - spec/configurate/provider/dynamic_spec.rb
94
- - spec/configurate/provider/env_spec.rb
95
114
  - spec/configurate/provider/yaml_spec.rb
96
- - spec/configurate/setting_path_spec.rb
115
+ - spec/configurate/provider/string_hash_spec.rb
116
+ - spec/configurate/provider/env_spec.rb
97
117
  - spec/configurate/proxy_spec.rb
98
118
  - spec/configurate/provider_spec.rb
99
- - spec/configurate/lookup_chain_spec.rb
100
- - spec/spec_helper.rb
119
+ - spec/configurate/setting_path_spec.rb
101
120
  - spec/configurate_spec.rb
102
- has_rdoc: