configurate 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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: